传递表名和限制到mysql存储过程不起作用

时间:2013-04-30 10:35:46

标签: php mysql sql

我创建了如下程序。我正在传递表名和限制以及用户名

DELIMITER $$
DROP PROCEDURE IF EXISTS `GetPosteingang`$$
CREATE PROCEDURE  `GetPosteingang`
(
IN stlimit INT,
IN tblname VARCHAR(100),
IN userId INT
)
BEGIN
DECLARE t1 VARCHAR(5000); 
SET @t1 =
"SELECT msg_id,msg_from_name as fromname,msg_titel as title,msg_date as date,msg_gelesen,msg_replied,msg_nodel,'msg' as type 
FROM "+@tblname+"
UNION
SELECT files_id as msg_id,from_username as fromname,files_oname as title,files_time as date,files_name as msg_gelesen,files_extension as msg_replied,files_filesize as msg_nodel,'file' as type 
FROM community_files
WHERE user_id = "+@userId+"
ORDER BY date DESC
LIMIT "+@stlimit+",30";
#SET @t1 =CONCAT('SELECT * FROM ',tab_name );

PREPARE STMT FROM @t1;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;

END $$
DELIMITER ;

但是当我这样称呼时,

CALL GetPosteingang('1','community_msgin8','658468'); 

它给了我错误,

CALL GetPosteingang('1','community_msgin8','658468')    Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1

请帮帮我。

2 个答案:

答案 0 :(得分:3)

  1. +不是字符串连接运算符 - 而是使用MySQL的CONCAT()函数;

  2. 用户定义的(会话)变量(以@为前缀)are different到存储程序/声明的变量(没有前缀);

  3. 小心使用导致SQL注入的tblname调用您的过程;

  4. UNION中的列名由第一个查询确定;以及

  5. 尽可能参数化您准备好的陈述。

  6. 因此:

    CREATE PROCEDURE  `GetPosteingang`
    (
      IN stlimit INT,
      IN tblname VARCHAR(100),
      IN userId INT
    )
    BEGIN
      SET @t1 := CONCAT("
        SELECT msg_id,
               msg_from_name AS fromname,
               msg_titel     AS title,
               msg_date      AS date,
               msg_gelesen,
               msg_replied,
               msg_nodel,
               'msg'         AS type
        FROM   `", REPLACE('`','``',tblname), "`
      UNION
        SELECT files_id,
               from_username,
               files_oname,
               files_time,
               files_name,
               files_extension,
               files_filesize,
               'file' as type
        FROM   community_files
        WHERE  user_id = ?
      ORDER BY date DESC
      LIMIT    ?, 30
      ", @t2 := userId, @t3 := stlimit;
    
      PREPARE stmt FROM @t1;
      EXECUTE stmt USING @t2, @t3;
      DEALLOCATE PREPARE stmt;
    END$$
    

    然而,所有这一切都说,拥有一个变量表名称是一个强有力的指标,表明您的模式严重非规范化 - 考虑将所有这些表合并为一个表,其中的列标识了它们的差异。

答案 1 :(得分:0)

上面的代码缺少CONCAT函数的结束括号。所以它应该是这样的:

CREATE PROCEDURE  `GetPosteingang`
(
  IN stlimit INT,
  IN tblname VARCHAR(100),
  IN userId INT
)
BEGIN
  SET @t1 := CONCAT("
    SELECT msg_id,
           msg_from_name AS fromname,
           msg_titel     AS title,
           msg_date      AS date,
           msg_gelesen,
           msg_replied,
           msg_nodel,
           'msg'         AS type
    FROM   `", REPLACE('`','``',tblname), "`
  UNION
    SELECT files_id,
           from_username,
           files_oname,
           files_time,
           files_name,
           files_extension,
           files_filesize,
           'file' as type
    FROM   community_files
    WHERE  user_id = ?
  ORDER BY date DESC
  LIMIT    ?, 30
  "), @t2 := userId, @t3 := stlimit;

  PREPARE stmt FROM @t1;
  EXECUTE stmt USING @t2, @t3;
  DEALLOCATE PREPARE stmt;
END$$