【问题标题】:UPDATE syntax that works in major databases适用于主要数据库的 UPDATE 语法
【发布时间】:2015-12-02 22:23:00
【问题描述】:

我想根据另一个表 (source) 中的值更新一个表 (target)。但我正在寻找一种适用于 4 个主要数据库的语法 - Oracle、MS SQL Server、PostgreSQL、MySQL。

到目前为止,我还没有找到这样一个统一的语法。我错过了这样的语法还是真的没有这样的语法?

甲骨文

UPDATE target t
SET (t.col1, t.col2) = (SELECT s.col1, s.col2 
                       FROM source s 
                       WHERE s.key = t.key)

MS SQL Server / PostgreSQL

UPDATE target t
SET t.col1 = s.col1, t.col2 = s.col2
FROM source s
WHERE t.key=s.key

MySQL

UPDATE target, source 
SET t.col1=s.col1, t.col2=s.col2
WHERE s.key=t.key

【问题讨论】:

    标签: mysql sql sql-server oracle ansi


    【解决方案1】:

    ANSI 更新语法(它应该在您列出的 DBMS 中工作):

    update t1 
        set col1 = (
                    select col1 
                    from t2 
                    where t1.key = t2.key
                  ),
        set col2 = (
                    select col2 
                    from t2 
                    where t1.key = t2.key
                  )
    

    【讨论】:

      【解决方案2】:

      效率低下,但 ANSI SQL 标准的方法是:

      UPDATE target
      SET col1 = (SELECT s.col1
                 FROM source s 
                 WHERE s.key = target.key),
          col2 = (SELECT s.col2 
                 FROM source s 
                 WHERE s.key = target.key);
      

      这并不意味着它可以在每个 RDBMS 中工作(例如,我认为它不会在 Access 中工作),但它确实适用于您列出的 4 个。

      我个人认为一周中的每一天都更看重性能而不是可移植性,所以我不会使用这种语法。我倾向于使用存储过程,具有通用名称,但每个 RDBMS 的语法不同。

      更新

      实际上,您为 Oracle 展示的使用行值构造函数的方法也被 ANSI SQL 标准允许:

      UPDATE target
      SET (t.col1, t.col2) = (SELECT s.col1, s.col2 
                             FROM source s 
                             WHERE s.key = t.key);
      

      不幸的是,如上所述,仅仅因为它符合 ANSI 标准,并不意味着它可以跨平台工作。

      【讨论】:

      • 不一定那么低效
      • @Ben 不一定,但在给定的示例中,它需要从源读取两次,而不是一次。我会认为这效率低下。如果更新为 5 列,则需要 5 倍的读取次数,如果不是简单的表查找,而是子查询更复杂,则需要重复更多的工作。
      • 我在 1 亿行上的测试 (SQL Server) 表明,在更新整个表时,如果有聚集索引,则表所在的每个附加列都会受到 20% 到 40% 的惩罚-内存(希望一直如此)。这绝对是重要的。所以我想这是在维护多个查询的维护头痛与性能的重要性之间进行权衡。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-23
      • 2019-06-18
      • 1970-01-01
      • 2013-12-01
      • 1970-01-01
      相关资源
      最近更新 更多