在 IN() 函数中使用用户定义的会话变量返回意外结果

Posted

技术标签:

【中文标题】在 IN() 函数中使用用户定义的会话变量返回意外结果【英文标题】:User-Defined Session variables using in IN() function returns unexpected result 【发布时间】:2014-11-19 17:09:39 【问题描述】:

例如,我有一个名为 TABLE 的表,它有一个名为 FIELD 的字段,其值为 12。运行这条语句

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+0SELECT @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会出现意外返回空的情况

踩坑记录Mysql查询使用not in会出现意外返回空的情况

Django 会话意外丢失数据

如何在查询中使用变量和更改用户定义的函数