我有一个简单的存储过程:
DELIMITER $$
CREATE PROCEDURE `findUserByName`(IN `name` VARCHAR(36))
BEGIN
set @name = name;
PREPARE findStmt FROM 'SELECT * FROM user WHERE name=?';
EXECUTE findStmt USING @name;
END$$
我在PHP中用prepare方法调用它:
$stmt = $mysqli->prepare('CALL findUserByName(?)');
$stmt->execute([$inputName]);
我对上面的代码有两个问题:
这个赋值语句
set @name = name;
显得有些多余,我可以直接使用参数name
吗? MySQL不允许我使用USING name
,我也尝试过将参数名称改为@name
,但是无法识别。
既然我在PHP中使用了prepare方法,那么将参数与SQL连接起来安全吗?
set @sql = CONCAT('SELECT * FROM user WHERE name=''', name, '''');
PREPARE findStmt FROM @sql;
EXECUTE findStmt;
不可以,您不能使用局部变量作为
EXECUTE
的参数。我同意这很奇怪且令人不满意,因为您必须设置一个用户定义的变量(带有 @
标志的类型),这似乎是多余的。
https://dev.mysql.com/doc/refman/8.0/en/execute.html 说:
参数值只能由用户变量提供
不,如果字符串可能包含不受信任的内容,则将字符串连接到动态 SQL 中是不安全的。这称为 SQL 注入,它是错误或数据泄露的常见来源。