从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;
如果文本不包含任何引号,则它会插入记录,但如果文本包含引号,则会引发任何错误。
有人建议我解决这个问题吗?
我的假设是准备好的陈述应该处理这个案子。
答案 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), '\')');