0

検索機能を使用している 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

最初の部分は、4 つの文字列 (区切り文字のコンマとスペース) をループ処理し、一致するキーワードについてデータベースにクエリを実行します。次に、実際の検索が行われるときに使用される新しいcond_cats変数を作成します。検索文字列を一致するカテゴリに置き換えると思いますが、結果は次のようになるため、ここではわかりません

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

実際の検索クエリに追加されます。

私の質問:
MySQL でユーザーが入力した検索文字列を分割して、ループを実行できるようにする方法はありますか? 2 番目の部分は、ストアド プロシージャの out-parameter である必要がありますね。これがすべての検索の前に実行される場合、それはストアド プロシージャである必要がありますか、それともデータベース クエリを使用し続ける必要がありますか?

ご意見ありがとうございます。

4

2 に答える 2

1

あなたが説明したことから、ストアドプロシージャ/関数でラップするメリットはあまりありません。データベースは、実際には文字列操作用に最適化されていません。ループは可能ですが、同等の SQL コードは通常、はるかに洗練されていません。さらに、動的SQL(または安全に行うには一時テーブル)の使用が必要になる場合があります。

ただし、コードを調べてみると、一連の条件を作成する代わりにcfloop単一の句を使用することで、2 番目を完全に排除できると思います。(この 2 つは同等です。)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を使用して、結果を 2 番目のクエリにフィードします。2 つのクエリを 1 つにマージできる可能性もあります。しかし、それはすべて検索クエリの複雑さに依存します。

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

編集: まだvalueListを使用できると思います。CASE最初のクエリに、一致する値を 2 つの列に分けるステートメントを追加するだけです。

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>
于 2012-05-15T04:19:32.393 に答える
0

mysqlで「全文」インデックスを試してみるべきだと思います。

于 2012-05-14T11:57:39.627 に答える