Cfqueryparam'd Запрос генерации из функции

Есть поисковый запрос и функция, которую я использую для генерации элементов запроса.

<cffunction name="GetSearchQuery" output="true" returntype="string" access="public">
    <cfargument name="arrayName" type="array" required="yes">
    <cfargument name="columnName" type="string" required="yes">
    <cfargument name="searchtype" type="string" required="no" default="wildcard">
    <cfset var o = "">
    <cfset var i = "">
    <cfset var search_item = "">
    <cfset search_item = "(">
    <cfloop from="1" to="#ArrayLen(Arguments.arrayName)#" index="o">
        <cfif Arguments.arrayName[o][1] EQ #Arguments.columnName#>
        <cfloop from="2" to="#ArrayLen(Arguments.arrayName[o])#" index="i">
            <cfset search_item = search_item & #Arguments.columnName#>
            <cfswitch expression="#Arguments.searchtype#">
                <cfcase value="wildcard">
                    <cfset search_item = search_item & ' LIKE 
                    <cfqueryparam value="%' & #Arguments.arrayName[o][i]# & '%"> AND '>
                </cfcase>
                <cfcase value="startswith">
                    <cfset search_item = search_item & ' LIKE 
                    <cfqueryparam value="' & #Arguments.arrayName[o][i]# & '%"> AND '>
                </cfcase>
                <cfcase value="endswith">
                    <cfset search_item = search_item & ' LIKE 
                    <cfqueryparam value="%' & #Arguments.arrayName[o][i]# & '"> AND '>
                </cfcase>
                <cfcase value="exactmatch">
                    <cfset search_item = search_item & ' = 
                    <cfqueryparam value="' & #Arguments.arrayName[o][i]# & '"> AND '>
                </cfcase>
            </cfswitch>
        </cfloop>
        </cfif>
    </cfloop>
    <cfif Len(search_item) GT 4>
    <cfset search_item = Left(search_item, Len(search_item)-4) & ") ">
    </cfif>
    <cfreturn search_item>
</cffunction>

И затем назовите это так в запросе

    SELECT * FROM #request.tablename#
      WHERE #utilObj.GetSearchQuery(arrsearch, "photonumber", true)# ИЛИ
            #utilObj.GetSearchQuery(arrsearch, "takeby", true)# ИЛИ 
            #utilObj.GetSearchQuery(arrsearch, "category", true)# OR 
            #utilObj.GetSearchQuery(arrsearch, "area", true)# OR 
            #utilObj.GetSearchQuery(arrsearch, "description", true)#

Но это вызывает ошибку в запросе

Но без cfqueryparam в функции это прекрасно работает.
например. <cfset search_item = search_item & ' LIKE "%' & #Arguments.arrayName[o][i]# & '%" AND '>

Есть ли в любом случае мы можем динамически добавлять cfqueryparam к запросу?

2 ответа

Решение

Вы не можете создать строку, содержащую CFML, и вывести ее и ожидать, что это как-то будет означать, что она действительно будет выполнена.

Во-первых, это немного глупо, когда вы останавливаетесь и думаете об этом, не так ли? (извините, я не имею в виду это подлым образом). И не чувствую себя плохо: я думаю, что мы все сделали это на каком-то этапе.

Во-вторых: CFML компилируется перед выполнением. Таким образом, процесс (для всех намерений и целей):

  1. Файл с кодом запрашивается
  2. Код из файла передается компилятору CF
  3. CF-компилятор выплевывает Java-байт-код
  4. JVM выполняет Java-байт-код

Таким образом, ваш код для генерации строки с кодом CFML не выполняется до (4), но он необходим обратно в (2). Если вы не можете путешествовать во времени, это не сработает.

Я обсуждаю это в своем блоге: " Процесс запроса / ответа ColdFusion"

Есть несколько вещей, которые вы можете сделать:

  1. не пишите динамический универсальный SQL, как это. Все мы делаем это, когда начинаем, но быстро понимаем, что динамический / универсальный SQL никогда не является хорошим решением для любой проблемы.
  2. Используйте один из уже существующих уровней абстракции БД. CF 9+ поставляется с поддержкой Hibernate.
  3. Если вы используете Query.cfc вместо <cfquery>Вы можете добавить заполнители для параметров и передать данные параметров в запрос отдельно.
  4. Запишите свой динамический код на диск, затем include Это. Это подорвет время компиляции / выполнения. Это будет медленно, так как ваш включенный файл должен быть скомпилирован перед запуском. Это ужасно.

Этот список в моем порядке предпочтения для решения этой проблемы.

Это ответ на вопрос: "В любом случае, мы можем динамически добавить cfqueryparam в запрос?". Есть, но вы должны сделать это внутри блока cfquery. Как то так нормально

<cfquery>
select SomeFields
from SomeTables
where 1 = 1
<cfif something>
and somefield = <cfqueryparam value="#SomeVariable#">
</cfif>
</cfquery>

То, что вы не можете сделать, по крайней мере, в версии 9 и ниже, это сделать параметры запроса частью переменной. Другими словами, это не скомпилируется.

WhereClause = "where 1=1";
if (something)
WhereClause &= ' and somefield = <cfqueryparam value="#SomeVariable#">';

Это более или менее то, что вы пытались.

Другие вопросы по тегам