据我所知,没有内置函数可以替换表中所有列的空字符串。您可以编写一个plpgsql函数来解决这个问题。
下面的函数替换空字符串在一个给定表的所有基本字符类型的列同NULL
。然后,integer
如果其余字符串是有效的数字文字,则可以强制转换为。
CREATE OR REPLACE FUNCTION f_empty2null(_tbl regclass, OUT updated_rows int) AS
$func$
DECLARE
-- basic char types, possibly extend with citext, domains or custom types:
_typ CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}';
_sql text;
BEGIN
SELECT INTO _sql -- build command
format('UPDATE %s SET %s WHERE %s'
, _tbl
, string_agg(format($$%1$s = NULLIF(%1$s, '')$$, col), ', ')
, string_agg(col || $$ = ''$$, ' OR '))
FROM (
SELECT quote_ident(attname) AS col
FROM pg_attribute
WHERE attrelid = _tbl -- valid, visible, legal table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND NOT attnotnull -- exclude columns defined NOT NULL!
AND atttypid = ANY(_typ) -- only character types
ORDER BY attnum
) sub;
-- Test
-- RAISE NOTICE '%', _sql;
-- Execute
IF _sql IS NULL THEN
updated_rows := 0; -- nothing to update
ELSE
EXECUTE _sql;
GET DIAGNOSTICS updated_rows = ROW_COUNT; -- Report number of affected rows
END IF;
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT f_empty2null('mytable');
SELECT f_empty2null('myschema.mytable');
Run Code Online (Sandbox Code Playgroud)
同样要获取列名updated_rows
:
SELECT * FROM f_empty2null('mytable');
Run Code Online (Sandbox Code Playgroud)
表名必须有效且可见,并且调用用户必须具有所有必要的特权。如果不满足这些条件中的任何一个,则该函数将不执行任何操作-即,也不会破坏任何操作。我强制转换为对象标识符类型regclass
以确保其正确性。
可以按原样提供表名'mytable'
,然后search_path
确定。或符合模式资格以选择特定模式('myschema.mytable'
)。
查询系统目录以获取表的所有(字符类型)列。所提供的功能,使用这些基本字符类型:text
,bpchar
,varchar
,"char"
。仅处理相关列。
使用quote_ident()
或清除format()
列名并防止SQLi。
更新的版本使用基本的SQL聚合函数string_agg()
来构建命令字符串而无需循环,这更加简单和快捷。而且更优雅。:)
必须在中使用动态SQLEXECUTE
。
更新的版本不包括定义的列,NOT NULL
并且仅在单个语句中更新每行一次,这对于具有多个字符类型列的表来说要快得多。
应该适用于任何现代版本的PostgreSQL。使用Postgres 9.1、9.3和9.5测试。