mysql update语句根据用户变量是否存在而表现不同

时间:2008-12-04 20:07:52

标签: sql mysql user-variables

我正在重置具有重复或缺失值的排序列,如下所示:

set @last='';
set @sort=NULL;
update conf_profile set sort=
    if(
        @last=(@last:=concat(org_id,',',profile_type_id,',',page,',',col)),
        (@sort:=@sort+1),
        (@sort:=0)
    )
order by org_id,profile_type_id,page,col,sort,id;

(遍历按顺序分配的多个关键字段排序的所有行 递增的值以排序;每当这些字段中的任何一个发生变化时,重新启动为0。)

只有在执行更新之前创建了@sort变量时,它似乎才有效 (虽然它设置的并不重要)。没有'set @sort',所有的 排序值设置为0或NULL。

任何想法为什么会这样? MySQL版本5.0.51。

更新:更详细地解释逻辑:在第一行,@ last =(@ last:= ...) 将永远是假的,此后当任何关键字段改变时它将是假的 从上一行。 (N.B.连接的关键字段都不是NULL)。 当它为假时,我们在0(@sort:= 0)再次启动排序计数器,否则,它是 递增(@sort:= @ sort + 1)并使用新值。

在更新语句中设置@sort之前不会使用它,所以无论是否 如何在更新语句之前设置它应该没有区别。

1 个答案:

答案 0 :(得分:3)

如果在表达式中引用未设置的用户变量,则将其视为NULL

在SQL中,NULL + 1返回NULL。如果您未在此@sort之前将NULL设置为非UPDATE值,则无论您评估多少次NULL,它都将继续为@sort:=@sort+1 { {1}}。执行@sort:=0后,它应该正常增加。

尝试此操作而不在UPDATE

中执行此操作
mysql> set @sort := NULL;
mysql> SELECT @sort; -- returns NULL
mysql> set @sort := @sort + 1;
mysql> SELECT @sort; -- returns NULL again
mysql> set @sort := 0;
mysql> set @sort := @sort + 1;
mysql> SELECT @sort; -- returns 1

我猜你在第一次设置@sort:=0后没有重复是唯一的巧合。

编辑:以上情况属实,但正如您所指出的那样,它并不能解释您所看到的行为,因为在评估过程中应保证逻辑@sort设置为0第一行。

但是,我注意到如果我更改了IF()表达式中术语的顺序,那么一切正常,即使我们开始时未设置@sort

set @last='';
-- set @sort=NULL;
update conf_profile set sort=
    if(
        @last!=(@last:=concat(org_id,',',profile_type_id,',',page,',',col)),
        (@sort:=0),
        (@sort:=@sort+1)
    )
order by org_id,profile_type_id,page,col,sort,id;

我不确定我是否理解得足以解释为什么这样可行,但是关于何时评估用户变量有一些古怪的东西。有关大量示例和血腥的详细信息,请参阅此博客:“Advanced MySQL user variable techniques”。