• 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.

     

     

     

  • 相关阅读:
    nginx 平滑升级和location配置案例
    nginx
    基于zabbix的监控keepalive脑裂
    KVM部署
    基于keepalived的lvs负载均衡http集群
    高可用keepalived
    KVM
    无向图中 生成树,完全图,连通图 的区别
    java中 is
    第一章——软件工程学概述 思维导图
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/13050784.html
Copyright © 2020-2023  润新知