我继承了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中是否有一种方法可以拆分用户输入的搜索字符串,因此我可以运行循环?第二部分应该是存储过程的参数,不是吗?如果此操作在每次搜索之前运行,那么它应该是存储过程,还是应该继续使用数据库查询?
感谢您的投入!
最佳答案
根据您的描述,将其包装在存储过程/函数中并没有太大的好处。数据库并未真正针对字符串操作进行优化。尽管可以进行循环,但是等效的sql代码通常远不那么优雅。另外,它可能需要使用动态sql(或临时表才能安全地执行此操作)。
但是,查看代码,我相信您可以通过使用单个cfloop
子句而不是构造一系列IN (....)
条件来完全消除第二个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>
关于mysql - 如何将搜索字符串Coldfusion-loop转换为MySQL存储过程?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10581262/