We have to find columns of a table with only NULL values. We are trying to build a plpgsql function that takes a table's name and returns the list of such columns.
我们必须找到只有NULL值的表的列。我们正在尝试构建一个plpgsql函数,它接受一个表的名称并返回这些列的列表。
How to create such a function?
如何创建这样的功能?
We are using PgAdmin 1.16.
我们正在使用PgAdmin 1.16。
1 个解决方案
#1
2
You can query the catalog table pg_attribute
to get a list of columns which are not defined NOT NULL
and therefore can hold NULL
values:
您可以查询目录表pg_attribute以获取未定义NOT NULL的列的列表,因此可以保存NULL值:
SELECT quote_ident(attname) AS column_can_be_null
FROM pg_attribute
WHERE attrelid = 'tbl'::regclass -- valid, visible table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND NOT attnotnull -- exclude columns defined NOT NULL!
ORDER BY attnum;
Where tbl
is your (optionally schema-qualified) table name.
其中tbl是您的(可选的模式限定的)表名。
Doesn't say there are any actual NULL values in the column. You'd have to test each column. Like this:
不要说列中有任何实际的NULL值。你必须测试每一列。像这样:
Full automation with plpgsql function
CREATE OR REPLACE FUNCTION f_all_null_columns_of_tbl(_tbl regclass)
RETURNS SETOF text AS
$func$
DECLARE
_row_ct bigint; -- count rows in table $1
_sql text; -- SQL string to test for NULL values
_cols text[]; -- array of candidate column names
_nulls bool[]; -- array of test results
BEGIN
EXECUTE 'SELECT count(*) FROM ' || _tbl
INTO _row_ct;
IF _row_ct = 0 THEN
RAISE EXCEPTION 'Table % has no rows!', _tbl; -- pointless for empty table
ELSE
RAISE NOTICE '% rows in table %.', _row_ct, _tbl;
END IF;
SELECT INTO _sql, _cols
'SELECT ARRAY[' || string_agg('bool_and(' || col || ' IS NULL)', ', ')
|| '] FROM ' || _tbl
, array_agg(col)
FROM (
SELECT quote_ident(attname) AS col
FROM pg_attribute
WHERE attrelid = _tbl -- valid, visible table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND NOT attnotnull -- exclude columns defined NOT NULL!
ORDER BY attnum
) sub;
EXECUTE _sql INTO _nulls;
FOR i IN 1 .. array_upper(_cols, 1)
LOOP
IF _nulls[i] THEN -- column is NULL in all rows
RETURN NEXT _cols[i];
END IF;
END LOOP;
RETURN;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT f_all_null_columns_of_tbl('my_schema.my_table');
Tested with Postgres 9.1 and 9.3.
This uses a number of advanced plpgsql features.
使用Postgres 9.1和9.3进行测试。这使用了许多高级plpgsql功能。
Related answer building SQL code and executing it, with modern syntax:
相关答案使用现代语法构建SQL代码并执行它:
- Replace empty strings with null values
用空值替换空字符串
About traversing a record:
关于遍历记录:
- Loop through columns of RECORD
循环通过RECORD列
#1
2
You can query the catalog table pg_attribute
to get a list of columns which are not defined NOT NULL
and therefore can hold NULL
values:
您可以查询目录表pg_attribute以获取未定义NOT NULL的列的列表,因此可以保存NULL值:
SELECT quote_ident(attname) AS column_can_be_null
FROM pg_attribute
WHERE attrelid = 'tbl'::regclass -- valid, visible table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND NOT attnotnull -- exclude columns defined NOT NULL!
ORDER BY attnum;
Where tbl
is your (optionally schema-qualified) table name.
其中tbl是您的(可选的模式限定的)表名。
Doesn't say there are any actual NULL values in the column. You'd have to test each column. Like this:
不要说列中有任何实际的NULL值。你必须测试每一列。像这样:
Full automation with plpgsql function
CREATE OR REPLACE FUNCTION f_all_null_columns_of_tbl(_tbl regclass)
RETURNS SETOF text AS
$func$
DECLARE
_row_ct bigint; -- count rows in table $1
_sql text; -- SQL string to test for NULL values
_cols text[]; -- array of candidate column names
_nulls bool[]; -- array of test results
BEGIN
EXECUTE 'SELECT count(*) FROM ' || _tbl
INTO _row_ct;
IF _row_ct = 0 THEN
RAISE EXCEPTION 'Table % has no rows!', _tbl; -- pointless for empty table
ELSE
RAISE NOTICE '% rows in table %.', _row_ct, _tbl;
END IF;
SELECT INTO _sql, _cols
'SELECT ARRAY[' || string_agg('bool_and(' || col || ' IS NULL)', ', ')
|| '] FROM ' || _tbl
, array_agg(col)
FROM (
SELECT quote_ident(attname) AS col
FROM pg_attribute
WHERE attrelid = _tbl -- valid, visible table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND NOT attnotnull -- exclude columns defined NOT NULL!
ORDER BY attnum
) sub;
EXECUTE _sql INTO _nulls;
FOR i IN 1 .. array_upper(_cols, 1)
LOOP
IF _nulls[i] THEN -- column is NULL in all rows
RETURN NEXT _cols[i];
END IF;
END LOOP;
RETURN;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT f_all_null_columns_of_tbl('my_schema.my_table');
Tested with Postgres 9.1 and 9.3.
This uses a number of advanced plpgsql features.
使用Postgres 9.1和9.3进行测试。这使用了许多高级plpgsql功能。
Related answer building SQL code and executing it, with modern syntax:
相关答案使用现代语法构建SQL代码并执行它:
- Replace empty strings with null values
用空值替换空字符串
About traversing a record:
关于遍历记录:
- Loop through columns of RECORD
循环通过RECORD列