MySQL动态SQL表名和结果

时间:2013-11-15 21:47:11

标签: mysql sql

我的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;

2 个答案:

答案 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.

    另请阅读You're Probably Storing Passwords Incorrectly

  • 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;