如何更新PostgreSQL中表的所有列?而不是一次只做一列 鉴于此表:
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查询。
答案 0 :(得分:0)
您可以从UPDATE
语句或plpgsql函数中的系统目录中动态构建DO
命令:
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;
相关答案以及更多信息和链接: