【问题标题】:Replace 'n/a' with 'NA' in all columns of a table在表的所有列中将 'n/a' 替换为 'NA'
【发布时间】:2016-12-11 03:42:56
【问题描述】:

如何在 PostgreSQL 中更新表的 ALL 列?而不是一次做一列。
鉴于此表:

Table1
Field1 | Field 2 | Field 3
123    | 987     | n/a
456    | n/a     | 101
n/a    | abcdef  | n/a

结果应该是:

Table1
Field1 | Field 2 | Field 3
123    | 987     | NA
456    | NA      | 101
NA     | abcdef  | NA

我正在寻找一个单个 SQL 查询。

【问题讨论】:

    标签: sql postgresql sql-update dynamic-sql psql


    【解决方案1】:

    您可以在 DO 语句或 plpgsql 函数中从系统目录中动态构建 UPDATE 命令:

    CREATE OR REPLACE FUNCTION f_global_replace(_tbl regclass
                                              , _old text
                                              , _new text
                                              , OUT updated_rows int) AS
    $func$
    DECLARE
       -- basic char types, possibly extend with citext, domains or custom types:
       _typ  CONSTANT regtype[] := '{text, bpchar, varchar}';
       _sql  text;
    BEGIN
       SELECT INTO _sql     -- build command
              format('UPDATE %s SET %s WHERE $1 IN (%s)'
                   , _tbl
                   , string_agg(format('%1$s = CASE WHEN %1$s = $1 THEN $2 ELSE %1$s END', col), ', ')
                   , string_agg(col, ','))
       FROM  (
          SELECT quote_ident(attname) AS col  -- escape names, prevent SQL injection!
          FROM   pg_attribute
          WHERE  attrelid = _tbl              -- valid, visible, legal table name 
          AND    attnum >= 1                  -- exclude tableoid & friends
          AND    NOT attisdropped             -- exclude dropped columns
          AND    atttypid = ANY(_typ)         -- only character types
          ORDER  BY attnum
          ) sub;
    
       -- RAISE NOTICE '%', _sql;             -- debug
    
       IF _sql IS NULL THEN
          updated_rows := 0;                         -- nothing to update
       ELSE
          EXECUTE _sql USING _old, _new;
          GET DIAGNOSTICS updated_rows = ROW_COUNT;  -- Report number of affected rows
       END IF;
    END
    $func$  LANGUAGE plpgsql;
    

    这会组装并自动执行以下形式的查询:

    UPDATE table1
    SET    field1 = CASE WHEN field1 = $1 THEN $2 ELSE field1 END
         , field2 = CASE WHEN field2 = $1 THEN $2 ELSE field2 END
         , field3 = CASE WHEN field3 = $1 THEN $2 ELSE field3 END
    WHERE  $1 IN (field1,field2,field3);

    小心!该函数更新所有字符类型列。确保它按预期工作。为了安全起见,我建议在显式事务中运行它,并且仅在检查后提交:

    BEGIN;
    SELECT * FROM f_global_replace('table1'::regclass, 'n/a', 'NA');
    
    TABLE table1;  -- all good?
    
    COMMIT;  -- then commit; else ROLLBACK;
    

    带有更多信息和链接的相关答案:

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 2012-06-17
    • 2011-11-08
    相关资源
    最近更新 更多