存储过程空错误

时间:2018-03-02 19:37:46

标签: mysql stored-procedures

我正在学习Mysql存储过程,我收到错误 Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1

delimiter //

drop procedure if exists getUserData//
create procedure getUserData(
in firstName varchar(50),
in lastName varchar(50),
in gender varchar(50),
in email varchar(50),
in userType varchar(50),
in isActive int,
in isDeleted int,
in createdBy date,
in dob date
)
begin

declare queryString text default "";

set queryString = concat(queryString, 'select firstName, lastName, gender, email, userType from user where 1=1');

if (firstName is not null and firstName != '') then
    set queryString = concat(queryString," and firstName like '%", firstName,"%' ");
end if;

if (lastName is not null and lastName != '') then
    set queryString = concat(queryString," and lastName like '%", lastName,"%' ");
end if;

if (gender is not null and gender != '') then
    set queryString = concat(queryString," and gender = '", gender,"' ");
end if;

if (email is not null and email != '') then
    set queryString = concat(queryString," and email like '%", email,"%' ");
end if;

if (userType is not null and userType != '') then
    set queryString = concat(queryString," and userType = '", userType,"' ");
end if;

if (isActive is not null and isActive != '') then
    set queryString = concat(queryString," and isActive = ", isActive);
end if;

if (isDeleted is not null and isDeleted != '') then
    set queryString = concat(queryString," and isDeleted = ", isDeleted);
end if;

if (createdBy is not null and createdBy != '') then
    set queryString = concat(queryString," and createdBy = ", createdBy);
end if;

if (dob is not null and dob != '') then
    set queryString = concat(queryString," and dob = ", dob);
end if;

set queryString = concat(queryString, ";");

-- select queryString;

prepare stmt from @queryString;
execute stmt;
deallocate prepare stmt;

end//

delimiter ;

我打印了我生成的查询,当我单独运行该查询但运行存储过程时显示错误时工作正常。我无法理解什么是实际错误以及我在哪里犯错误。 调用程序是,结果查询是

call getUserData('Test','','','','',0,0,null,null);

select firstName, lastName, gender, email, userType from user where 1=1 and firstName like '%Test%' ;

  

用户表

CREATE TABLE user (
id int(11) NOT NULL AUTO_INCREMENT,
createdBy varchar(255) DEFAULT NULL,
createdOn datetime DEFAULT NULL,
updatedBy varchar(255) DEFAULT NULL,
updatedOn datetime DEFAULT NULL,
dob datetime DEFAULT NULL,
email varchar(255) DEFAULT NULL,
firstName varchar(255) DEFAULT NULL,
gender varchar(255) DEFAULT NULL,
isActive tinyint(4) DEFAULT '5',
isDeleted tinyint(4) DEFAULT '0',
lastName varchar(255) DEFAULT NULL,
userId varchar(255) DEFAULT NULL,
userType varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

2 个答案:

答案 0 :(得分:0)

在MySQL中,queryString@queryString是两个不同的变量。

  • @前缀的变量为user-defined session variables。它们的范围是MySQL会话。也就是说,当您在过程中设置此类变量时,它仍然具有您在过程结束后设置的值,并且只要您的会话持续(或在后续过程调用中使用它),您就可以读取它。
  • 没有@前缀的变量是使用DECLARE在存储过程或触发器内创建的local variables。它们的范围就在声明它们的过程中。

您正在加入queryString,但您正在使用@queryString作为准备语句。

为了证明这一点,我在准备之前将这一行添加到了程序中:

select queryString, @queryString;

我得到了这个输出:

mysql> call getUserData('Test','','','','',0,0,null,null)\G
*************************** 1. row ***************************
 queryString: select firstName, lastName, gender, email, userType from user where 1=1 and firstName like '%Test%' ;
@queryString: NULL

您可以看到@queryString从未为其分配任何字符串。所以当你在prepare @queryString中使用它时,它没有任何准备。

由于某种原因,MySQL的prepare语句不能将您在程序体内使用DECLARE创建的局部变量作为其输入。它只能采用用户定义的会话变量(前缀为@的那种)。

这是MySQL的一个奇怪的疏忽,多年前至少两次向他们的bug数据库报告过。但到目前为止,还没有采取任何行动:

我不想使用MySQL的存储过程。他们在2003年左右为MySQL 5.0实现了它们,从那时起他们似乎没有显着改进这个功能。没有包,没有调试器或开发人员工具,没有可扩展性,也没有程序的持久编译状态(它们在每次用户连接中首次使用时重新编译)。坦率地说文档很差。

答案 1 :(得分:0)

添加此行解决了我的问题。我创建了 @SQL 变量并将 queryString 分配给它,现在它正常工作。

SET @SQL := queryString;
prepare stmt from @SQL;

我已经提到了这个链接。 Prepared Statement in MySql