我的数据库中有许多文本列,其中值是空字符串('')。空字符串需要设置为NULL。我不知道此数据库中的确切架构,表和列,或者我想写一个可以重用的通用解决方案。
''
NULL
我将如何编写查询/函数以在所有架构的所有表中查找所有文本列,并使用空字符串('')将所有列更新为NULL?
实现此目的的最有效方法:
UPDATE
NOT NULL
这个相关的答案具有plpgsql函数,该函数针对任何给定的表UPDATE使用系统目录pg_attribute自动安全地构建和运行命令
pg_attribute
使用f_empty2null()此答案中的函数,您可以像这样遍历选定的表:
f_empty2null()
DO $do$ DECLARE _tbl regclass; BEGIN FOR _tbl IN SELECT c.oid::regclass FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' -- only regular tables AND n.nspname NOT LIKE 'pg_%' -- exclude system schemas LOOP RAISE NOTICE $$PERFORM f_empty2null('%');$$, _tbl; -- PERFORM f_empty2null(_tbl); -- uncomment to prime the bomb END LOOP; END $do$;
小心! 这将更新数据库中所有用户表的所有列中的所有空字符串。确保这是您想要的,否则可能会破坏数据库。
UPDATE当然,您需要对所有选定表具有特权。
作为儿童安全装置,我评论了有效载荷。
这是重复使用的集成解决方案。没有安全装置:
CREATE OR REPLACE FUNCTION f_all_empty2null(OUT _tables int, OUT _rows int) AS $func$ DECLARE _typ CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}'; _sql text; _row_ct int; BEGIN _tables := 0; _rows := 0; FOR _sql IN SELECT format('UPDATE %s SET %s WHERE %s' , t.tbl , string_agg(format($$%1$s = NULLIF(%1$s, '')$$, t.col), ', ') , string_agg(t.col || $$ = ''$$, ' OR ')) FROM ( SELECT c.oid::regclass AS tbl, quote_ident(attname) AS col FROM pg_namespace n JOIN pg_class c ON c.relnamespace = n.oid JOIN pg_attribute a ON a.attrelid = c.oid WHERE n.nspname NOT LIKE 'pg_%' -- exclude system schemas AND c.relkind = 'r' -- only regular tables AND a.attnum >= 1 -- exclude tableoid & friends AND NOT a.attisdropped -- exclude dropped columns AND NOT a.attnotnull -- exclude columns defined NOT NULL! AND a.atttypid = ANY(_typ) -- only character types ORDER BY a.attnum ) t GROUP BY t.tbl LOOP EXECUTE _sql; GET DIAGNOSTICS _row_ct = ROW_COUNT; -- report nr. of affected rows _tables := _tables + 1; _rows := _rows + _row_ct; END LOOP; END $func$ LANGUAGE plpgsql;
称呼:
SELECT * FROM pg_temp.f_all_empty2null();
返回值:
_tables | _rows ---------+--------- 23 | 123456
请注意 我如何正确地转义了表名和列名!
c.oid::regclass AS tbl, quote_ident(attname) AS col