如何在set查询中包含where子句

时间:2013-11-20 04:50:28

标签: mysql

我有下面的查询,它完全按照我的要求工作除了我需要能够包含一个带有声明变量startDate和endDate的where子句。我一直在变量上出错。

DROP PROCEDURE IF EXISTS `reportNameTest`//

-- Creates new procedure

CREATE PROCEDURE reportNameTest (
        IN logId varchar (50),
        IN fromDate varchar (50),
        IN toDate varchar (50)
        )

    BEGIN
            DECLARE logInS varchar (50);
            DECLARE startDate varchar (50);
            DECLARE endDate varchar (50);


           SET startDate = FROM_UNIXTIME(fromDate/1000);
           SET endDate = FROM_UNIXTIME(toDate/1000);


 SET @tbl = CONCAT('log',logId);
 SET @s = CONCAT(             
 'SELECT g.groupId,g.name AS groupName,l.logId,l.name AS logName,
       lr.userId,completed, 
      g1.parentId AS parentId1, g1.name AS group1Name,g2.parentId AS parentId2, g2.name AS group2Name,
      g3.parentId AS parentId3, g3.name AS group3Name,u.name,u.userId,lr.*
  FROM logs l
      INNER JOIN activities a ON l.logid = a.logid
      INNER JOIN groups g ON g.groupId = l.groupId
      LEFT JOIN groups g1 ON g.parentId = g1.groupId
      LEFT JOIN groups g2 ON g1.parentId = g2.groupId
      LEFT JOIN groups g3 ON g2.parentId = g3.groupId
      INNER JOIN ' ,@tbl);      

 SET @V = CONCAT (@s,' lr ON lr.activityID = a.activityID
      INNER JOIN users u ON u.userID = lr.userID' );

 SET @W = CONCAT (@V,'WHERE l.completed
        BETWEEN startDate
            AND endDate'); 
  PREPARE stmt FROM @V;

     EXECUTE stmt;
  DEALLOCATE PREPARE stmt;

    END //

DELIMITER ;

我愿意接受任何建议! 谢谢

2 个答案:

答案 0 :(得分:0)

您的代码存在一些问题:

  1. 构建查询字符串时,您正在生成不必要的变量。 @S -> @V -> @W。但是,您从@V准备了不包含完整查询字符串的语句。
  2. 而不是连接变量startDateendDate的值,而是将它们的名称放在字符串文字中。
  3. 应引用startDateendDate的值。
  4. 即使您声明了变量,也不要使用logInS变量。
  5. 在您的情况下,您只需要一个变量(除非您对它们执行有意义的操作,例如验证),它将包含查询字符串。
  6. 这就是说这样试试

    DELIMITER //
    CREATE PROCEDURE reportNameTest(
      IN logId    VARCHAR(50),
      IN fromDate VARCHAR(50),
      IN toDate   VARCHAR(50))
    BEGIN
      SET @sql = CONCAT(             
     'SELECT g.groupId, g.name AS groupName, l.logId,l.name AS logName,
          lr.userId,completed, 
          g1.parentId AS parentId1, g1.name AS group1Name,g2.parentId AS parentId2, g2.name AS group2Name,
          g3.parentId AS parentId3, g3.name AS group3Name,u.name,u.userId,lr.*
      FROM logs l
          INNER JOIN activities a ON l.logid = a.logid
          INNER JOIN groups g ON g.groupId = l.groupId
          LEFT JOIN groups g1 ON g.parentId = g1.groupId
          LEFT JOIN groups g2 ON g1.parentId = g2.groupId
          LEFT JOIN groups g3 ON g2.parentId = g3.groupId
          INNER JOIN log', logId, ' lr ON lr.activityID = a.activityID
          INNER JOIN users u ON u.userID = lr.userID
      WHERE l.completed BETWEEN \'', FROM_UNIXTIME(fromDate / 1000), 
      '\' AND \'',  FROM_UNIXTIME(toDate / 1000), '\'');      
    
      PREPARE stmt FROM @sql;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;
    END //
    DELIMITER ;
    

    假设您生成的查询本身是正确的,那应该可以正常工作。

    这是 SQLFiddle 演示,它输出结果查询字符串而不是执行它

答案 1 :(得分:0)

首先,正如@neutrino指出的那样,你错过了lr.userIDWHERE之间的空格。要查看此信息,您可以使用select @W而不是prepare和execute返回查询。然后尝试在普通的mysql命令器中运行该查询。

或者您可以检查查询/常规日志以查找失败的查询并找到缺失的空间。

其次,您不需要在这样的几个步骤中构建查询,如果您只对concat进行一次长时间更改,则可能更容易阅读。