2012-05-14 78 views
0

我继承了coldfusion8网站,它使用了一些搜索功能。如何将搜索字符串coldfusion-loop转换为MySQL存储过程?

我试图将标准化的数据库查询存储到存储过程中。因为我是一个新手在两个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)的搜索可以是。我还是想知道,什么是happending,但到目前为止,我想,如果用户输入一个字符串,如:

string1, string2, string3 string4 

第一部分遍历四根弦(分隔符逗号和空格),并querys的数据库匹配关键字。然后创建一个新的变量,在实际搜索时使用该变量。我猜它取代了搜索字符串,相匹配的类别,但我不知道在这里,因为其结果将是

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

这是附加到实际的搜索查询。

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

感谢您的一些意见!

回答

1

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

但是,看看你的代码,我相信你可以通过使用单个IN (....)子句而不是构建系列OR条件来完全消除第二个cfloop。 (这两个是等效的。)

只需修改第一个查询即可检索只需要类别,即“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" ... > 
) 

编辑:我想你可以仍然使用值列表。只需添加一个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> 
+0

感谢您的信息。不知道它是否有帮助,但我valueList可能会有用。 – frequent

+0

听起来好像你的问题是“这会比存储过程更好吗?” IMO no。所以上面的代码演示了如何更有效地编写cfquery *和安全*(没有所有的连接,即动态sql)但是随时留下问题以获得其他意见。 – Leigh

+0

对不起。我不清楚。问题被正确回答。我的示例代码出现错误,因此您的代码段适用于错误的示例代码。问题是categoryID1应该是categoryID1和cateogryID2。 ID1是运动用品的产品分类的名称,服装的ID2。所以我需要检查任何关键字是否与两个索引中的任何类别匹配,并返回每个索引中的类别编号(如果有的话)。我的例子只是轮询ID1,所以IN会工作。我还没有找到一种方法来使用它与两个单独的ID。我编辑了我的问题。再次感谢您的输入! – frequent

0

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

+0

不是真的我的问题...我有一个全文搜索,但此外还有更细粒度的搜索标准,如上所述。我试图使这个存储过程,所以任何帮助,将不胜感激。谢谢! – frequent

相关问题