MYSQL - 处理引号的存储过程和预处理语句

时间:2013-04-21 11:39:40

标签: mysql stored-procedures prepared-statement

从PHP我使用预准备语句(通过绑定参数)并将数据发送到下面的存储过程

CREATE PROCEDURE test_my_add_comment(in var_details text, in var_table_name varchar(50))
BEGIN    
    SET @s = CONCAT('INSERT INTO ',var_table_name,'(details) VALUES("',var_details,'")');
    PREPARE stmt FROM @s;
    EXECUTE stmt;
   COMMIT;
END;

我的表

CREATE TABLE `test_table` (
  `details` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

如果文本不包含任何引号,则它会插入记录,但如果文本包含引号,则会引发任何错误。

有人建议我解决这个问题吗?

我的假设是准备好的陈述应该处理这个案子。

2 个答案:

答案 0 :(得分:4)

好的,我在MariaDB 10上进行了测试,它可以运行:

DROP PROCEDURE IF EXISTS `test_my_add_comment`;
CREATE PROCEDURE `test_my_add_comment`(IN `var_details` TEXT, IN `var_table_name` VARCHAR(64))
    MODIFIES SQL DATA
BEGIN    
    SET @`add_comment` = CONCAT('INSERT INTO ', `var_table_name`, ' (`details`) VALUES (', QUOTE(`var_details`), ');');
    PREPARE `stmt_add_comment` FROM @`add_comment`;
    EXECUTE `stmt_add_comment`;
    DEALLOCATE PREPARE `stmt_add_comment`;
    SET @`add_comment` = NULL;
END;

CALL `test_my_add_comment`('This is a test','test_table');

我添加了很多backticks,因为如果您使用保留字,它们可以帮助您获得更好的错误消息。我为预准备语句使用了正确的语法,我释放了@add_comment。此外,最好为预准备语句使用特定名称,因为如果在更多地方使用相同的名称,则可能会遇到问题。我将第二个参数转换为VARCHAR(64)因为它是真正的表名maxlength。

答案 1 :(得分:1)

错误在程序中。这是如何逃避报价。我在这里使用单引号。我还引用了表/列名称。

SET @s = CONCAT('INSERT INTO `',var_table_name,'` (`details`) VALUES(\'', QUOTE(var_details), '\')');