代码之家  ›  专栏  ›  技术社区  ›  ysth

mysql update语句的行为根据用户变量是否存在而不同

  •  1
  • ysth  · 技术社区  · 16 年前

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

    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或空。

    你知道为什么会这样吗?mysql版本5.0.51。

    更新:详细解释逻辑:在第一行,@last=(@last:=…) 将始终为false,此后,当任何键字段更改时都将为false 从上一行。(注意,没有一个关键字段是concat'd,永远不为空的)。 当它为false时,我们在0(@sort:=0)重新启动排序计数器,否则,它是 递增(@sort:=@sort+1)并使用新值。

    在任何情况下,在update语句中设置@sort之前都不会使用它,所以无论 在update语句之前如何设置应该没有区别。

    1 回复  |  直到 16 年前
        1
  •  3
  •   Bill Karwin    16 年前

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

    在sql中, 无效的 + 1回报 无效的 . 如果你不设定 @sort 对非 无效的 在此之前的值 UPDATE ,然后它将继续 无效的 不管你评价多少次 @sort:=@sort+1 . 一旦你做了 @sort:=0 ,则应正常递增。

    试试这个,不要在 更新 :

    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
    

    我想这只是巧合,在你第一次设定之后你就没有复制品了 排序:=0 .

    编辑: 以上是对的,但正如你所指出的,这并不能解释你所看到的行为,因为从逻辑上讲 @排序 在对第一行进行求值时,应确保设置为0。

    但是,我注意到如果我更改了 IF() 表达,一切都有效,即使 @排序 在我们开始时是不稳定的:

    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 “。