Комбинируя строки запроса в петле
-
05-10-2019 - |
Вопрос
У меня есть следующий код ColdFusion 9:
<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
<cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
EXEC searchFAQ '#tagArray[i]#'
</cfquery>
</cfloop>
EXEx выполняет хранимую процедуру на сервере базы данных, который возвращает строки данных, в зависимости от того, что является параметром. То, что я пытаюсь сделать, это объединить запросы в один объект запроса. Другими словами, если он петли 3 раза, и каждая петля возвращает 4 строки, я хочу, чтобы объект запроса, который имеет все 12 строк в одном объекте. Как мне это достичь?
Решение
Возможно, вы захотите сделать другой подход (измените свою сохраненную процедуру, чтобы принять несколько аргументов или использовать список и fnsplit.) и верните набор данных все сразу. Однако, чтобы напрямую ответить на ваш вопрос, вот как вы можете комбинировать запросы, как вы просите:
Вы можете использовать Union в запросах запросов для совмещения всех наборов данных.
<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
<cfquery name="qryGetSPFAQs#i#" datasource="#application.datasource#">
EXEC searchFAQ '#tagArray[i]#'
</cfquery>
</cfloop>
<cfquery name="combined" dbtype="query">
<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
select * from qryGetSPFAQs#i#
<cfif i lt arrayLen(tagArray)>UNION</cfif>
</cfloop>
</cfquery>
Другие советы
Более прямой путь может быть что-то вроде этого:
<cfset bigQ = queryNew("column")>
<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
<cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
EXEC searchFAQ '#tagArray[i]#'
</cfquery>
<cfset queryAddRow(bigQ)>
<cfset querySetCell(bigQ, "column". qryGetSPFAQs)>
</cfloop>
Вам понадобится назначение QuerySetCell () для каждого столбца. Проверьте Запрос функций в живых документах Чтобы получить больше информации.
Здесь выходит из раствора коробки, отказавшись от StoredProc для вида SQL (я объясню).
Отказ от ответственности: не видение исходного кода SP, я не могу сказать, подходит ли мое решение. Я предполагаю, что SP довольно простой, и я признаю, что я обычно предпочитаю скомпилированное исполнение SP через вид, но одноразовое выполнение представления SQL следует превзойти петли SP X раз.
Сначала сделайте вид, который выглядит как оператор SELECT в SP (минус параметризация, конечно, вы покрываете это в пункте Where In CFQuery вашего нового представления.
Во-вторых, настройте свой цикл, чтобы сделать не более чем создать набор данных, которые мы собираемся использовать для предложения там, где. Вам нужно будет использовать ArrayTolist и немного строковых манипуляций, чтобы погрузить его, с конечным продуктом, являющимся строкой, хранящимся в одной переменной CF, выглядящую так:
(«ValueOFArrayElement1», «ValueOfRaryElelement2», «VALUE_AND_SO_ON»)
Строительство строки довольно легко, используя атрибут делиметра ArrayTolist, а после завершения цикла добавьте левую скобка и одну цитату на левую часть строки; И добавьте одну цитату и правую скобки в правильную наибольшую позицию в строке.
Теперь напишите оператор CFQuery, чтобы выбрать необходимые вами столбцы с вашего представления (вместо выполнения вашего SP). И вместо того, чтобы пройти параметр на SP, вы собираетесь положить предложение там в CFQuery.
О, кстати, я заявляю, что вам нужен вид SQL, но весь выбор мог быть построенным в CFQuery. Лично, когда у меня есть многобильный присоединиться, мне нравится определить, что в SQL View, где он выполняется быстрее, чем присоединение в CFQuery. В конечном итоге A StoredProc даже быстрее, но наш пункт, где находится намного дружелюбнее, чтобы кодировать и прочитать так, как это было бы отправить в StoredProc без циркуляции и из SQL.
Это хорошая цель, чтобы сделать только одну поездку в базу данных и обратно, если это возможно. Вот почему мы процитировали через массив, чтобы написать строку, приравнивающую к всем значениям в наборе данных. Таким образом, мы выполним только один запрос один раз.
SELECT Col1, Col2, Col_etc
FROM SQL_View_Name
WHERE ColumnName in #BigStringWeMadeFromArrayToList#
Когда наш CFQuery оказывается, пункт будет выглядеть так же, как это в SQL:
WHERE ColumnName in
('ValueOfArrayElement1','ValueOfArrayElement2','Value_And_So_On')
Так что у вас есть. Как я уже сказал, это приятно, потому что это делает только одну поездку в БД, и, поскольку мы строим представление, производительность все равно будет довольно хорошо - лучше, чем запустить StoredProc 4+ раз. (не обижайся)
Я должен повторить ... без видимого кода SP, я не уверен, если это сделает. Кроме того, это вроде не странно отказаться от StoredProc для SQL View, «меньшем» сущности в RDBMS, но я уверен, что мы достигнем большей производительности, и я думаю, что это довольно читается.