Объединение строк запроса в цикле - PullRequest
2 голосов
/ 29 мая 2010

У меня есть следующий код ColdFusion 9:

<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
</cfloop>

EXEC выполняет хранимую процедуру на сервере базы данных, которая возвращает строки данных в зависимости от параметра. Я пытаюсь объединить запросы в один объект запроса. Другими словами, если он зацикливается 3 раза и каждый цикл возвращает 4 строки, я хочу объект запроса, который имеет все 12 строк в одном объекте. Как мне этого добиться?

Ответы [ 3 ]

2 голосов
/ 29 мая 2010

Возможно, вы захотите использовать другой подход (измените хранимую процедуру, чтобы она принимала несколько аргументов, или используйте список и fnSplit ) и верните набор данных сразу. Однако, чтобы напрямую ответить на ваш вопрос, вы можете объединить запросы так, как вы их просите:

Вы можете использовать UNION в Query of Queries для объединения всех наборов данных.

<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>
1 голос
/ 29 мая 2010

Более прямой путь может быть примерно таким:

<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 () для каждого столбца. Проверьте функции запросов в живых документах для получения дополнительной информации.

0 голосов
/ 25 сентября 2010

Это готовое решение, отказывающееся от StoredProc для представления SQL (я объясню).

Отказ от ответственности: не видя исходного кода SP, я не могу сказать, подходит ли мое решение. Я предполагаю, что SP является довольно простым, и я признаю, что обычно предпочитаю скомпилированное выполнение SP, а не однократное выполнение SQL View, которое должно превзойти циклы SP x раз.

Сначала создайте представление, которое выглядит как оператор SELECT в SP (за исключением параметризации, конечно, - вы расскажете об этом в предложении WHERE в CFQUERY вашего нового представления.

Во-вторых, настройте ваш цикл так, чтобы он делал не больше, чем строит набор данных, который мы собираемся использовать для предложения WHERE. Вам нужно будет использовать ArrayToList и немного манипулировать строками, чтобы привести его в порядок, а конечным продуктом будет строка, хранящаяся в одной переменной CF, которая выглядит следующим образом:

( 'ValueOfArrayElement1', 'ValueOfArrayElement2', 'Value_And_So_On')

Построить строку довольно легко, используя атрибут delimeter ArrayToList, и после завершения цикла добавьте левую скобку и одинарную кавычку к самой левой позиции строки; и добавьте одинарную кавычку и правую скобку к самой правой позиции в строке.

Теперь напишите оператор CFQUERY, чтобы ВЫБРАТЬ нужные вам столбцы из своего представления (вместо выполнения SP). И вместо передачи параметра в SP, вы собираетесь поместить предложение WHERE в CFQUERY.

Да, кстати, я утверждаю, что вам нужен SQL View, но весь SELECT может быть встроен в CFQUERY. Лично, когда у меня есть мульти-таблица JOIN, мне нравится определять это в SQL-представлении, где оно выполняется быстрее, чем JOIN в CFQUERY. В конечном счете StoredProc еще быстрее, но наше предложение WHERE гораздо удобнее кодировать и читать так, как если бы оно отправлялось в 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, «меньшей» сущности в СУРБД, но я уверен, что мы достигнем большей производительности, и я думаю, что он также довольно читабелен.

...