-2

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.

How to create such a function?

We are using PgAdmin 1.16.

3

1 Answer 1

4

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:

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.

Doesn't say there are any actual NULL values in the column. You'd have to test each column. Like this:

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.

SQL Fiddle.

Related answer building SQL code and executing it, with modern syntax:

About traversing a record:

Sign up to request clarification or add additional context in comments.

4 Comments

Dear Erwin Brandstetter, Thx for your kindly idea i need null value columns(empty columns all the values are null) i tried your Query. it worked, but those results are showing some data tables also. Eg: i tried country table, there domain_name column has null values, but this query shows 6 table names i need function type query. Thanks Erwin Brandstetter for your wonderful query
@Pathman: Ah, I think I get it now. You should edit your question with this clarification. Use "edit" left under your question.
@ Erwin Brandstetter :I edit your query to function type
@ Erwin Brandstetter: It is very usefully function,i solved some other function based on this function. I'm very happy now. Thx Erwin Brandstetter

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.