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

SQL更新评估顺序

  •  34
  • pilcrow  · 技术社区  · 14 年前

    以下查询中的评估顺序是什么:

    UPDATE tbl SET q = q + 1, p = q;
    

    也就是说,威尔 "tbl"."p" 被设定为 q q + 1 是吗?这里的计算顺序是否受SQL标准的控制?

    谢谢。

    更新

    考虑之后 Migs' answer ,我对我能找到的所有数据库进行了一些测试。虽然我不知道标准说的是什么,但是实现是不同的。

    鉴于

    CREATE TABLE tbl (p INT NOT NULL, q INT NOT NULL);
    INSERT INTO tbl VALUES (1, 5);   -- p := 1, q := 5
    UPDATE tbl SET q = q + 1, p = q;
    

    我发现了 "p" "q" 是:

    database           p   q
    -----------------+---+---
    Firebird 2.1.3   | 6 | 6  -- But see "Update 2" below
    InterBase 2009   | 5 | 6
    MySQL 5.0.77     | 6 | 6  -- See "Update 3" below
    Oracle XE (10g)  | 5 | 6
    PostgreSQL 8.4.2 | 5 | 6
    SQLite 3.3.6     | 5 | 6
    SQL Server 2016  | 5 | 6
    

    更新2

    Firebird 2.5改变了它的行为以匹配我测试过的大多数其他SQL引擎,只剩下MySQL。相关发行说明条目, "Logic Change in SET Clause" ,强烈建议 根据SQL规范,大多数行为都是正确的 .

    我已经窃听了MySQL对这种行为的评论(错误号 52861 ,因为他们似乎是局外人。

    更新3

    上面提到的bug今天(2010-05-19)已经关闭,并且要更新的文档集使这个行为在 更新 说明和 与标准SQL的区别 部分。

    BRAVO,MySQL。

    3 回复  |  直到 7 年前
        1
  •  13
  •   Migs    14 年前

    MySQL执行“从左到右”的评估,并“查看”新值。 (5.0.45-community-nt-log mysql社区版测试)

    此外,从MySQL手册:“单表更新分配通常从左到右进行评估。对于多个表更新,不能保证以任何特定顺序执行分配。”

    现在,“一般”是相当模糊的,“没有保证”是非常糟糕的,因为评价的顺序是重要的。

    所以,为了回答这个问题:行为是由“SQL标准”指定的还是仅仅是一种约定?


    更新:获取了sql92规范,该规范在“13.10 update语句:搜索”item“6)在更新T的任何行之前,对T的每一行(值表达式)S进行了有效的评估。”

    imho不是绝对明确,但足以考虑到标准是不“看到”自己更新的结果。 考虑到您的例子,Oracle、PostgreSQL和Interbase是如何做到这一点的。

        2
  •  6
  •   Quassnoi    14 年前

    这个 UPDATE 看不到它的工作结果。

    p 将被设置为 q 更新之前。

    以下代码只交换列:

    DECLARE @test TABLE (p INT, q INT)
    
    INSERT
    INTO    @test
    VALUES  (2, 3)
    
    SELECT  *
    FROM    @test
    
    p    q
    ---  ---
      2    3
    
    UPDATE  @test
    SET     p = q,
            q = p
    
    SELECT  *
    FROM    @test
    
    p    q
    ---  ---
      3    2
    
        3
  •  -1
  •   Evan Carroll    14 年前

    对表的写入必须发生在完成读取时正在进行的事务之后。