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

Posted

技术标签:

【中文标题】mysql update 语句的行为会根据用户变量是不是存在而有所不同【英文标题】:mysql update statement behaves differently based on whether a user variable existsmysql update 语句的行为会根据用户变量是否存在而有所不同 【发布时间】:2008-12-04 20:07:52 【问题描述】:

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

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

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

【问题讨论】:

我知道这是一个老问题,但是“作为一般规则,您永远不应该为用户变量赋值并在同一语句中读取值。”来自User-defined variables 文档的段落涵盖了它吗?换句话说,MySQL 可能会选择做一些完全出乎意料的事情…… 我不知道;它继续展示了违反该一般规则的案例,并解释了您如何期望它们起作用,而我的案例不是其中之一。不过,感谢您的链接。 【参考方案1】:

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

在 SQL 中,NULL + 1 返回 NULL。如果在此 UPDATE 之前未将 @sort 设置为非 NULL 值,那么无论您评估 @sort:=@sort+1 多少次,它都将继续为 NULL。一旦你做@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 在评估第一行。

但是,我注意到,如果我更改 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”。

【讨论】:

抱歉,这并不能解释为什么它可以使用 set @sort=NULL 但不能不使用。

以上是关于mysql update 语句的行为会根据用户变量是不是存在而有所不同的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL行为

MySql中的变量定义

mysql 触发器 if 语句update怎么操作?

PHP 准备 MySQL UPDATE 语句,其中包含字符串中的变量

多个 UNIQUE 字段的 ON DUPLICATE KEY UPDATE 的 MySQL 行为

Update语句导致异常行为