在 IN() 函数中使用用户定义的会话变量返回意外结果
Posted
技术标签:
【中文标题】在 IN() 函数中使用用户定义的会话变量返回意外结果【英文标题】:User-Defined Session variables using in IN() function returns unexpected result 【发布时间】:2014-11-19 17:09:39 【问题描述】:例如,我有一个名为 TABLE
的表,它有一个名为 FIELD
的字段,其值为 1 和 2。运行这条语句
SELECT GROUP_CONCAT(`FIELD`)
INTO @LIST
FROM `TABLE`;
和
SELECT @LIST;
返回
1,2
然后我做一个 IF() 语句
SELECT IF (1 IN(@LIST),"TRUE","FALSE");
返回
是的
但是当我运行这个时
SELECT IF (2 IN(@LIST),"TRUE","FALSE");
返回
错误
所以我尝试这个语句进行一些调试
SELECT IF (2 IN(1,2),"TRUE","FALSE");
它返回我的期望值
是的
那么我错过了什么吗?我需要它返回 TRUE。
【问题讨论】:
在您的声明中,@LIST
实际上等同于单个字符串文字 '1,2'
。但它是在数字上下文中评估的,mysql 正在评估它等于整数1
。 (试试SELECT @LIST+0
和SELECT @LIST+4
,看看返回了什么。所以,您的谓词实际上是SELECT 1 IN (1)
。在单引号中,SELECT '1' IN ('1,2')
结果会有所不同。底线: comma 在字符串中(无论是文字还是 udv)不会 被解释为 SQL 文本的一部分。您可以在字符串文字或 udv 上使用字符串比较函数,例如 @987654335 @.
【参考方案1】:
变量@LIST
有一个字符串类型值:'1,2'
。要测试值是否在此值列表中,您必须使用字符串函数:FIND_IN_SET
:
SELECT IF (FIND_IN_SET(1, @LIST), "TRUE","FALSE");
SELECT IF (FIND_IN_SET(2, @LIST), "TRUE","FALSE");
在这里测试:http://sqlfiddle.com/#!2/4fce1d/1
【讨论】:
简洁的解决方案重要的是要了解 IN 不会将逗号分隔的字符串作为输入,而是将逗号分隔的值列表作为输入。【参考方案2】:in 语句查找逗号分隔的值,这些值可以是字符串、整数、双精度数和浮点数等等。您可以对大多数数据类型使用 in 语句。 @LIST 是什么数据类型?一个varchar?您的@LIST 是一个看起来像'1,2'
的字符串,而不是像1,2
这样的逗号分隔值列表。细微但非常重要的区别。您不能像上面尝试的那样使用 IN 语句。
但是,如果您将查询创建为字符串,然后将字符串作为动态 sql 执行,我敢打赌它会起作用。
所以尝试以下方法:
SELECT GROUP_CONCAT(`FIELD`)
INTO @LIST
FROM `TABLE`;
SET @s = CONCAT('SELECT IF (2 IN(',@LIST,'),"TRUE","FALSE");');
PREPARE stmt1 FROM @s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
阅读有关动态 SQL 的信息。
【讨论】:
以上是关于在 IN() 函数中使用用户定义的会话变量返回意外结果的主要内容,如果未能解决你的问题,请参考以下文章
踩坑记录Mysql查询使用not in会出现意外返回空的情况
踩坑记录Mysql查询使用not in会出现意外返回空的情况
踩坑记录Mysql查询使用not in会出现意外返回空的情况