我不确定我做错了什么......
我有一个简单的疑问:
SELECT * FROM locations WHERE (ID IN (1, 2, 3, 4, 5));
现在我只是将该查询放入一个带有 LONGTEXT 类型参数的存储过程中
sp_FetchMultipleLocations(IN argLocations LONGTEXT)
BEGIN
SELECT * FROM locations WHERE (ID IN (argLocations));
END;
然后我调用该参数中具有多个值的存储过程:
CALL sp_FetchMultipleLocations('1, 2, 3, 4, 5');
但是 where 子句中的 IN 语句似乎不起作用,它只显示了第一个(1)位置...为什么会这样?
谢谢
参数是一个单一的整体字符串。仅仅因为您在存储过程内的
IN
子句中使用该参数并不意味着 MySQL 知道它应该将该 csv 字符串拆分为单独的值 - 它不知道 CSV 是什么,也不应该这样做。
你必须使用动态sql,例如在伪代码中:
procedure foo(in args longtext)
begin
sql = concat('SELECT ... WHERE foo IN (', args, ')')
execute @sql
end
你只需要使用分割函数,用逗号来完成。
你现在传递它的方式是单个字符串。
所以这是我已经困扰很长时间的一个问题,能够传入用户 ID、电子邮件或任何其他值数组的数组,并对所有匹配的记录执行数据库操作。
例如:
假设您网站的管理员用户想要对软件的用户进行批量更新,禁用他们的帐户。也许他们会看到一个用户列表,并选中其中一些用户旁边的“禁用”框。现在他们单击“禁用用户”按钮。执行此操作的较慢方法是(在服务器端)迭代每个 userId 并调用某些函数,例如
User.disable(userId)
。
更有效的方法是将 userId 数组传入数据库,并让它对所有需要的记录立即执行操作。这是如何完成的。
您的存储过程应如下所示:
-- userIds is a json string of an array of integers, e.g. "[1, 2, 3]"
CREATE PROCEDURE `user.disable`(userIds VARCHAR(4000))
BEGIN
UPDATE user SET enabled = 0 WHERE JSON_CONTAINS(userIds, id);
END
调用此函数的代码可能如下所示(PHP):
class User {
public static function disableMany(array $userIds): bool
{
$strUserIds = json_encode($userIds);
$query = "CALL `user.disable`($strUserIds)";
$result = mysqli_query($con, $query);
return $result !== false;
}
}
我希望这有帮助,祝你好运。