如何将构造MySQL语法的Coldfusion循环转换为MySQL存储过程?

时间:2012-06-21 12:23:05

标签: mysql stored-procedures coldfusion left-join temp-tables

我正在尝试将Coldfusion的产品搜索转移到MySQL存储过程中。

搜索有大约20个标准,并且是它所在站点的一个vanilla-function,所以想将它转换为存储过程,因为需要进行大量的预编译。

我想我找出了大部分的搜索标准。我正在努力争取最后一个。

首先是Coldfusion部分:

<cfquery datasource="dtb" name="get_pricelists">
  SELECT sid, pricelist
  FROM buyerList AS b
  LEFT JOIN sellerList AS s ON s.sid = b.sid AND s.pass = b.pass
  WHERE b.bid = >parameter<
</cfquery>

这使用价目表和当前用户的相应价格表来卖卖所有卖家。看起来像这样(在M​​ySQL中我正在创建临时表):

=====================
sellerID    pricelist
12345         NULL
23467         foo
99999         bar

下一部分是我在努力的地方:

<cfset misterLister = "LEFT JOIN preislisten p ON ">
<cfoutput query="get_pricelists" >
<cfif pricelist IS ''>
     <cfset misterLister = misterLister & '(p.sid = a.sid AND p.pricelist = "BASE" AND p.ean = a.ean AND p.iln = "#sellerID#") OR '>
  <cfelse>
     <cfset misterLister = misterLister & '(p.sid = a.sid AND p.pricelist = "#pricelist#" AND p.ean = a.ean AND p.iln = "#sellerID#") OR '>
  </cfif>
</cfoutput>
<cfset misterLister = misterLister & "(1=0)">

所以在上面的例子中,这将循环通过3个找到的卖家和价格表在Coldfusion中创建这个MySQL语法:

LEFT JOIN pricelists p ON
   (p.sid = a.sid AND p.pricelist = "BASE" AND p.ean = a.ean AND p.iln = 12345 ) OR 
   (p.sid = a.sid AND p.pricelist = "foo" AND p.ean = a.ean AND p.iln = 23467 ) OR 
   (p.sid = a.sid AND p.pricelist = "bar" AND p.ean = a.ean AND p.iln = 99999) OR 
   (1=0)

然后只是传递给实际的查询。

问题
我可以做第一部分并将其存储在临时表中。但是,是否有可能在MySQL中创建第二部分,即循环通过临时表的结果并从中构造上述语句?

我还是MySQL的新手,所以我不知道从哪里开始。我正在查看准备好的语句和光标,但这些是唯一的选择吗?

修改
好。我试图提出我的第一份准备好的声明。看起来像这样:

SET @sql_text := '
DECLARE strCount   INT DEFAULT 1;

SELECT sid, ifnull(pricelist,"BASE"), count(*) AS recs
    FROM buyerList AS b
    LEFT JOIN sellerList AS s ON s.sid = b.sid AND s.pass = b.pass
    WHERE b.bid = ?

SET @string = "LEFT JOIN preislisten AS p";

lj:
  LOOP

    SET @string = CONCAT( @string, "ON (p.iln = a.iln AND p.preisliste = sid AND p.ean = a.ean AND p.iln = pricelist ) OR");

    SET strCount = strCount+1;
    IF strCount = recs
    THEN LEAVE lj;
    END IF;

END LOOP lj;

SET @string = CONCAT( @string,"(1=0)")
';
SET @param_iln = param_iln;
PREPARE stmt FROM @sql_text;
EXECUTE stmt using @param_iln;
DEALLOCATE PREPARE stmt;

所以我在prep语句字符串中进行初始查询,然后希望能够遍历找到的价格表(它将超过3个卖家和价格表,所以我需要经历一个循环,我做?)。我把所有东西都塞进去了。但如果这样可行,我将如何将此字符串添加到我的实际搜索查询中,如下所示:

SELECT articles AS art 
   << insert left join here >>
    FROM bigtable AS bt
    WHERE
      a lot of other criteria

我迷路了......

1 个答案:

答案 0 :(得分:0)

替换SELECT sid, pricelist

使用SELECT sid, ifnull(pricelist,'BASE')

(sql server readers,mysql的ifnull()就像你的isnull()函数一样)

这使得价格表在null时显示为“BASE”。

然后,您可以跳过<cfif pricelist IS ''> + <cfelse>

如果您使用的是cf9 +,您还可以使用速记连接<cfset misterLister &= "value">

通过构建动态sql并执行内部存储过程,您将获得更好的性能。 减少数据库往返次数。如果coldfusion只需要与mysql交谈一次就会更快。

您不需要临时表来循环。只需构建sql字符串即可直接在查询中执行。然后执行sql string。

不要担心游标 - 它们适用于您想要加载某些记录,循环它们并在每一行上执行操作。

准备好的陈述:http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-prepared-statements.html

存储过程:http://dev.mysql.com/doc/refman/5.1/en/create-procedure.html

您基本上需要一个提供参数的存储过程。它在内部构建一个准备和执行的字符串。返回结果数据。