我的sql dinamic代码遇到了很多麻烦:
DELIMITER $$
CREATE DEFINER=`remotecontroller`@`%` PROCEDURE `check_pwd`(IN pwd VARCHAR(20),
IN user VARCHAR(20), IN tab VARCHAR(30), IN pwd_f varchar(30), IN id_f varchar(30),
OUT result Bit(1))
READS SQL DATA
BEGIN
set @u_pwd= null;
set @txt= concat("select pwd_f from ",tab," where id_f = upper(user) into @u_pwd");
prepare exec from @txt;
execute exec;
-- IN previous version the table and column names was preselected: select pwd_f from clinic.np where id_f like upper(user) into u_pwd;
If Password(pwd) = @u_pwd then set result= 1;
else set result= 0;
end if;
END
代码的目标是检查一个密码与表中的其他密码并返回bool。对于测试项目,我知道我需要更改密码插件,但我会在最终项目中进行
当我执行代码时抛出一个错误1064,sql语法错误。有谁能够帮我?我尝试了很多东西,谢谢大家!
编辑 - 现在,使用相同的代码抛出错误1054:field_list中的未知列pwd_f;
答案 0 :(得分:3)
这不会选择变量pwd_f
命名的列,而是选择名称 字面上的列“pwd_f”。
set @txt= concat("select pwd_f from ",tab," where id_f = upper(user) into @u_pwd");
同样由变量id_f
命名的列。
你可能想要这个:
set @txt= concat("select ",pwd_f," from ",tab," where ",id_f," = upper(user) into @u_pwd");
请注意,您的存储过程容易受到SQL注入。确保调用此存储过程的代码只能 从有限列表中传递列名和表名。您应该使用whitelisting technique来执行此操作。
重新评论:
用户不是列,是其中的行值!
好吧那就是同样的问题 - 你把变量放到你的SQL字符串中,但它们不会被解释为变量。在动态查询中包含值的正确方法是使用参数。
set @txt= concat("select ",pwd_f," from ",tab," where ",id_f," = upper(?) into @u_pwd");
set @user= user;
prepare exec from @txt;
execute exec using @user;
额外的@user
变量是解决存储过程中准备/执行的奇怪限制:MySQL不允许过程变量是查询参数,必须使用会话变量({{1前缀)。
我很高兴你让它运转起来。为了它的价值,我也在测试它,所以这是我的测试脚本(有效):
@
其他提示:
PASSWORD()不是用于应用程序级密码散列的好函数。 They even say so in a note in the documentation.
MySQL的BIT数据类型已知错误。经验丰富的MySQL专家建议使用TINYINT作为事实上的布尔类型。
我不知道你为什么要使用存储过程来执行此任务。 MySQL存储过程效率很低,大多数开发人员都会使用应用程序代码来做你正在做的事情。它更容易开发和调试,运行速度更快,更容易防止SQL注入。
答案 1 :(得分:2)
也许这就是:
set @txt= concat("select pwd_f from ",tab," where id_f = upper(user) into @u_pwd");
prepare exec from @conc;
应该更像是:
set @txt= concat("select pwd_f from ",tab," where id_f = upper(user) into @u_pwd");
prepare exec from @txt;