如何将搜索字符串coldfusion-loop转换为MySQL存储过程?

时间:2012-05-14 10:08:09

标签: mysql stored-procedures loops coldfusion

我继承了一个使用一些搜索功能的coldfusion8网站。

我正在尝试将标准化数据库查询存储到存储过程中。由于我是Coldfusion和MySQL的新手,我现在想知道我是否可以在MySQL中做到这一点:

<cfquery datasource="db" name="find_cats">
    SELECT wg.no, wg.type, wg.keywords, wg.lang
    FROM cats AS wg 
    <cfloop list="searchForm.cats_search_string" delimiters=", " item="tag">
      WHERE wg.keywords LIKE <cfqueryparam value='%#tag#%' cfsqltype='cf_sql_varchar'> AND
    </cfloop>
    wg.lang = <cfqueryparam value="#Session.lang#" cfsqltype="cf_sql_varchar">
</cfquery>
<cfset cond_cats = "AND (1=2">
    <cfoutput query="find_cats">
        <!--- check if found category belongs to either AAA or BBB classifcation --->
        <cfif wg.type is "AAA">
            <cfset cond_cats = cond_cats & " OR categoryID1 = #wg.no#">
        </cfif>
        <cfif wg.typ is "BBB">
            <cfset cond_cats = cond_cats & " OR categoryID2 = #wg.no#">
        </cfif>
    </cfoutput>
    <cfset cond_cats = cond_cats & ")">

搜索可以是关键字或索引(AAA,BBB)。我仍在尝试了解正在发生的事情,但到目前为止,我认为如果用户输入的字符串如下:

 string1, string2, string3 string4

第一部分循环遍历四个字符串(分隔符逗号和空格)并查询数据库以查找匹配的关键字。然后它会创建一个新的 cond_cats 变量,该变量在实际搜索发生时使用。我猜它会用匹配的类别替换搜索字符串,但我不确定这里,结果将是

AND (1=2 OR category1 = 12345 OR category2 = 88888 )

附加到实际搜索查询。

我的问题:
有没有办法在MySQL中分割用户输入的搜索字符串,所以我能够运行循环?第二部分应该是存储过程的out-parameter,不应该吗?如果在每次搜索之前运行它,它应该是一个存储过程还是应该继续使用数据库查询?

感谢您的一些意见!

2 个答案:

答案 0 :(得分:1)

根据您的描述,我没有看到将它包装在存储过程/函数中的好处。数据库并未真正针对字符串操作进行优化。虽然循环是可能的,但是等效的sql代码通常不那么优雅。另外,它可能需要使用动态sql(或临时表来安全地执行它)。

但是,查看代码我相信您可以使用单个IN (....)子句完全消除第二个cfloop,而不是构建一系列OR条件。 (两者是等价的。)

只需修改第一个查询即可检索所需类型的 类别,即“AAA”和“BBB”。

<cfquery datasource="db" name="find_cats">
    SELECT  wg.no
    FROM    cats AS wg 
    WHERE   wg.lang = <cfqueryparam value="#Session.lang#" cfsqltype="cf_sql_varchar">
    AND     wg.type IN ('AAA', 'BBB')
    AND  ( 1 = 2
         <cfloop list="#searchForm.cats_search_string#" delimiters=", " item="tag">
              OR wg.keywords LIKE <cfqueryparam value='%#tag#%' cfsqltype="cf_sql_varchar"> 
          </cfloop>
       )
</cfquery>

然后使用ValueList将结果反馈到第二个查询中。您甚至可以将两个查询合并为一个。但这完全取决于搜索查询的复杂性。

WHERE categoryID1 IN 
( 
    <cfqueryparam value="#valueList(find_cats.no)#" list="true" ... > 
)

编辑:我认为您仍然可以使用valueList。只需在第一个查询中添加CASE语句,将匹配值分为两列:

SELECT  wg.no
        , CASE WHEN wg.type = 'AAA' THEN wg.no ELSE NULL END AS ID1Values
        , CASE WHEN wg.type = 'BBB' THEN wg.no ELSE NULL END AS ID2Values
...

然后生成每列中的值列表:

     <cfset firstList  = valueList(find_cats.ID1Values)>
     <cfset secondList = valueList(find_cats.ID2Values)>

最后在搜索查询中使用这些列表。

   WHERE 1 = 2

   <cfif listLen(firstList)>
         OR categoryID1 IN ( <cfqueryparam value="#firstList#" list="true" cfsqltype="cf_sql_integer"> )
   </cfif>

   <cfif listLen(secondList)>
         OR categoryID2 IN ( <cfqueryparam value="#secondList#" list="true" cfsqltype="cf_sql_integer"> )
   </cfif>

答案 1 :(得分:0)

我认为你应该在mysql中尝试“全文”索引。