2013-08-06 2 views
1

Существует поисковый запрос, и функцию я использую для создания элементов запроса
поколения 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)# OR 
      #utilObj.GetSearchQuery(arrsearch, "takenby", true)# OR 
      #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 динамически в запрос?

ответ

5

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

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

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

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

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

Я обсуждаю это в своем блоге: «The ColdFusion request/response process»

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

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

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

2

Это ответ на вопрос: «Есть ли способ добавить динамический запрос 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#">'; 

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