1

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

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:=...) 将始终为 false,此后当任何关键字段从前一行更改时,它将为 false . (注意没有一个被连接的关键字段是NULL)。当它为假时,我们从 0 (@sort:=0) 重新开始排序计数器,否则,它会递增 (@sort:=@sort+1) 并使用新值。

在更新语句中设置之前,绝不会使用@sort,因此在更新语句之前是否设置或如何设置应该没有区别。

4

1 回答 1

3

未设置的用户变量被视为NULL您在表达式中引用它。

在 SQL 中,NULL+1 返回NULL. 如果您在此之前没有设置@sort为非NULL值,那么无论您评估多少次UPDATE,它都会继续存在。一旦你这样做,那么它应该正常增加。 NULL@sort:=@sort+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;

我不确定我是否理解得很好,无法准确解释为什么会这样,但是关于何时评估用户变量有一些古怪的东西。有关大量示例和详细信息,请参阅此博客:“高级 MySQL 用户变量技术”。

于 2008-12-04T20:26:51.260 回答