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

发布于 2024-07-09 15:39:48 字数 786 浏览 8 评论 0原文

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

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)。 当为 false 时,我们从 0 (@sort:=0) 重新开始排序计数器,否则为 递增 (@sort:=@sort+1) 并使用新值。

在任何情况下,在更新语句中设置 @sort 之前都不会使用 @sort,因此无论是 在更新语句之前如何设置应该没有什么区别。

I'm reseting a sort column that has duplicate or missing values like so:

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;

(Go through all the rows sorted by a number of key fields assigning progressively
incremented values to sort; whenever any of those fields change, restart at 0.)

It seems to work only if the @sort variable was created prior to doing the update
(though it doesn't matter what it was set to). Without the 'set @sort', all the
sort values are set to either 0 or NULL.

Any ideas why this would be so? MySQL version 5.0.51.

Update: To explain the logic more at length: on the first row, the @last=(@last:=...)
will always be false, and thereafter it will be false when any of the key fields changes
from the previous row. (N.B. none of the key fields being concat'd are ever NULL).
When it's false, we start the sort counter over again at 0 (@sort:=0), otherwise, it is
incremented (@sort:=@sort+1) and the new value is used.

In no case is @sort used before it is being set in the update statement, so whether or
how it is set before the update statement should make no difference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

腹黑女流氓 2024-07-16 15:39:49

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

在 SQL 中,NULL + 1 返回 NULL。 如果您在此 UPDATE 之前未将 @sort 设置为非 NULL 值,那么它将继续为 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 应保证在第一行的评估。

但是,我注意到,如果我更改 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 用户变量技术"。

An unset user variable is treated as NULL if you reference it in an expression.

In SQL, NULL + 1 returns NULL. If you don't set @sort to a non-NULL value prior to this UPDATE, then it'll continue to be NULL no matter how many times you evaluate @sort:=@sort+1. Once you do @sort:=0, then it should increment normally.

Try this without doing it in an 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

I would guess it's only a coincidence that you have no duplicates after the first time you set @sort:=0.

edit: The above is true, but as you point out, it doesn't explain the behavior you're seeing, since logically @sort should be guaranteed set to 0 during evaluation of the first row.

However, I notice if I change the order of the terms in the IF() expression, it all works, even if @sort is unset as we begin:

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;

I'm not sure if I understand it well enough to explain exactly why this works, but there's some wacky stuff regarding when user variables are evaluated. See this blog for lots of examples and gory details: "Advanced MySQL user variable techniques".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文