mysql - 存储过程中的错误 1064 在准备好的语句设置其值后检查局部变量是否为 NULL
问题描述
我正在使用 MySQL 创建 Twitter 克隆,并且正在编写一个存储过程来更新刚刚关注新用户的用户的 userfeed 表,以包括该用户关注的人的所有推文。
CREATE PROCEDURE `populate_userfeed_after_following`(IN username varchar(20), IN following_username varchar(20))
BEGIN
DECLARE last_tweet timestamp default null;
DECLARE following_id int;
SELECT id from users where username=following_username into following_id;
SET @timestamp_tweet = CONCAT('SELECT timestamp FROM userfeed_', username, ' ORDER BY timestamp DESC LIMIT 1 into', last_tweet);
PREPARE timestamp_tweetQuery FROM @timestamp_tweet;
EXECUTE timestamp_tweetQuery;
IF (last_tweet is NULL) THEN
SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=', following_id,
' LIMIT 200');
ELSE
SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=', following_id ,'and timestamp >', last_tweet);
END IF;
PREPARE insertQuery FROM @insert_statement;
EXECUTE insertQuery;
DEALLOCATE PREPARE timestamp_tweetQuery;
DEALLOCATE PREPARE insertQuery;
END
我将最过时的时间戳存储在一个局部变量中,该变量last_tweet
是在从关注某人的用户的 userfeed 表中检索到它之后调用的,并且我正在检查它NULL
以创建动态插入语句。
每当我通过传递参数来调用程序时,例如,
call populate_userfeed_after_following('joe', 'rocky');
#joe follows rocky
我得到一个错误,
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
如果您指出我的代码中的错误,我将不胜感激。
解决方案
正如@P.Salmon 指出的那样,在这种情况下使用局部变量(使用 DECLARE 语句)将不起作用。所以我更正了代码以使用会话变量或用户定义的变量(使用 SET 语句)并重写它。
以下逻辑有效:
CREATE PROCEDURE `populate_userfeed_after_following`(IN username varchar(20), IN following_username varchar(20))
BEGIN
-- DECLARE last_tweet timestamp default null;
-- DECLARE following_id int;
SET @following_id = 0;
SET @last_tweet = NULL;
SET @followingId_tweet = CONCAT('SELECT id from users where username=\'', following_username, '\' into @following_id');
SET @timestamp_tweet = CONCAT('SELECT timestamp FROM userfeed_', username, ' ORDER BY timestamp DESC LIMIT 1 into @last_tweet');
PREPARE followingIdQuery FROM @followingId_tweet;
EXECUTE followingIdQuery;
DEALLOCATE PREPARE followingIdQuery;
PREPARE timestamp_tweetQuery FROM @timestamp_tweet;
EXECUTE timestamp_tweetQuery;
DEALLOCATE PREPARE timestamp_tweetQuery;
IF (@last_tweet is NULL) THEN
SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=@following_id
LIMIT 200');
ELSE
SET @insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=@following_id and timestamp > @last_tweet');
END IF;
PREPARE insertQuery FROM @insert_statement;
EXECUTE insertQuery;
DEALLOCATE PREPARE insertQuery;
END
最初的错误是由于我使用参数中传递的值创建动态 SQL 语句的 select 语句以及使用 where 的下面的行SET @timestamp_tweet
。正确的方法是使用准备好的语句。
推荐阅读
- awk - 如何使用awk将第一列和第二列的第一行打印为单列?
- android - 列表未显示在 onChangedof 视图模型下
- azure - 如何在流量管理器端点中添加虚拟规模集实例 IP
- c++ - c ++ cmake(将windows转换为平台独立)WinExec to execute_process
- python - 在python中汇总分组的日期时间数据
- django - 将云存储文件 url (s3/Alibaba OSS) 存储在 postgres 等关系数据库中的 Django 最佳实践
- javascript - 是否可以通过 HTML 元素中的会话从我的数据库中传递对象?
- ruby-on-rails - 将 URL 转换为 erb 中的锚标记
- ios - 在 SwiftUI 中使用来自 React Native 资源的字体
- php - Mac OSX Mojave 将 php 升级到 7.2