zoukankan      html  css  js  c++  java
  • postgresql——SQL update fields of one table from fields of another one(列的批量更新)

    https://stackoverflow.com/questions/18797608/update-multiple-rows-in-same-query-using-postgresql

    问题描述:

    I have two tables:

    A [ID, column1, column2, column3]
    B [ID, column1, column2, column3, column4]
    

    A will always be subset of B (meaning all columns of A are also in B).

    I want to update a record with a specific ID in B with their data from A for all columns of A. This ID exists both in A and B.

    Is there an UPDATE syntax or any other way to do that without specifying the column names, just saying "set all columns of A"?

    I'm using PostgreSQL, so a specific non-standard command is also accepted (however, not preferred).

    答:

    The question is old but I felt the best answer hadn't been given, yet.

    Is there an UPDATE syntax ... without specifying the column names?

    General solution with dynamic SQL

    You don't need to know any column names except for some unique column(s) to join on (id in the example). Works reliably for any possible corner case I can think of.

    This is specific to PostgreSQL. I am building dynamic code based on the the information_schema, in particular the table information_schema.columns, which is defined in the ISO SQL standard and most modern RDBMS (except for Oracle) support it. But a DO statement with PL/pgSQL code executing dynamic SQL is totally non-standard PostgreSQL syntax.

    DO
    $do$
    BEGIN
    
    EXECUTE (
    SELECT
    'UPDATE b
     SET   (' || string_agg(quote_ident(column_name), ',') || ')
         = (' || string_agg('a.' || quote_ident(column_name), ',') || ')
     FROM   a
     WHERE  b.id = 123
     AND    a.id = b.id'
    FROM   information_schema.columns
    WHERE  table_name   = 'a'       -- table name, case sensitive
    AND    table_schema = 'public'  -- schema name, case sensitive
    AND    column_name <> 'id'      -- all columns except id
    );
    
    END
    $do$;
    

    Assuming a matching column in b for every column in a, but not the other way round. b can have additional columns.

    WHERE b.id = 123 is optional, to update only a selected row.

    SQL Fiddle.

    Related answers with more explanation:

     

    Partial solutions with plain SQL

    With list of shared columns

    You still need to know the list of column names that both tables share. With a syntax shortcut for updating multiple columns - shorter than what other answers suggested so far in any case.

    UPDATE b
    SET   (  column1,   column2,   column3)
        = (a.column1, a.column2, a.column3)
    FROM   a
    WHERE  b.id = 123    -- optional, to update only selected row
    AND    a.id = b.id;
    

    SQL Fiddle.

    This syntax was introduced with Postgres 8.2 in Dec. 2006, long before the question was asked.
    More details in the manual and this related answer on dba.SE:

    With list of columns in B

    If all columns of A are defined NOT NULL (but not necessarily B),
    and you know the column names of B (but not necessarily A).

    UPDATE b
    SET   (column1, column2, column3, column4)
        = (COALESCE(ab.column1, b.column1)
         , COALESCE(ab.column2, b.column2)
         , COALESCE(ab.column3, b.column3)
         , COALESCE(ab.column4, b.column4)
          )
    FROM (
       SELECT *
       FROM   a
       NATURAL LEFT JOIN  b -- append missing columns
       WHERE  b.id IS NULL  -- only if anything actually changes
       AND    a.id = 123    -- optional, to update only selected row
       ) ab
    WHERE b.id = ab.id;
    

    The NATURAL LEFT JOIN joins a row from b where all columns of the same name hold same values. We don't need an update in this case (nothing changes) and can eliminate those rows early in the process (WHERE b.id IS NULL).
    We still need to find a matching row, so b.id = ab.id in the outer query.

    db<>fiddle here
    Old sqlfiddle.

    This is standard SQL except for the FROM clause.
    It works no matter which of the columns are actually present in A, but the query cannot distinguish between actual NULL values and missing columns in A, so it is only reliable if all columns in A are defined NOT NULL.

    There are multiple possible variations, depending on what you know about both tables.

     

     

     

  • 相关阅读:
    Hexo个人博客主题配置
    Hexo+Github/Gitee 搭建个人博客
    TCP/IP协议架构介绍(四):应用层
    TCP/IP协议架构介绍(三):传输层
    TCP/IP协议架构介绍(一):网络接口层
    Linux Bash编程
    TCP/IP协议架构介绍(二):网络层
    charles SSL证书安装
    Linux常用命令:性能命令
    简繁转换
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/13050784.html
Copyright © 2011-2022 走看看