Sql 将表中所有列中的“不适用”替换为“不适用”
如何在PostgreSQL中更新表的所有列?而不是一次只做一个专栏。 鉴于此表:Sql 将表中所有列中的“不适用”替换为“不适用”,sql,postgresql,sql-update,dynamic-sql,psql,Sql,Postgresql,Sql Update,Dynamic Sql,Psql,如何在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 |
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查询。您可以从DO语句或plpgsql函数中的系统目录动态生成更新命令:
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;