我正在重置具有重复或缺失值的排序列,如下所示:
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之前不会使用它,所以无论是否 如何在更新语句之前设置它应该没有区别。
答案 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”。