2

有没有办法列出信息模式中包含具有 NULL 值的布尔类型列的所有表?如果我有表的名称,我可以稍后使用查询:

SELECT * FROM table_name WHERE column_name IS NULL

当然,如果有一种方法可以通过单个查询列出所有表中的所有行,那会更快。

逐步执行此操作将是:

SELECT * FROM table1 WHERE column_name IS NULL
SELECT * FROM table2 WHERE column_name IS NULL
SELECT * FROM table3 WHERE column_name IS NULL
...

表已经填充,对于新数据库,这些列应该有NOT NULL约束。

4

3 回答 3

3

尝试:

SELECT table_catalog, table_schema, table_name, column_name, ordinal_position  
FROM information_schema.columns  
WHERE table_schema <> 'pg_catalog' AND data_type = 'boolean';

和:

DO $$  
DECLARE 
r record;
s record;  
BEGIN  
FOR r IN    SELECT table_catalog, table_schema, table_name, column_name, ordinal_position 
        FROM information_schema.columns 
        WHERE table_schema <> 'pg_catalog' AND data_type = 'boolean'  
LOOP  
    FOR s IN EXECUTE 'SELECT ' || quote_literal(r.table_schema) || ', ' || quote_literal(r.table_name) || ', ' || quote_literal(r.column_name) || ' WHERE EXISTS (SELECT 1 FROM ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' WHERE ' || quote_ident(r.column_name) || ' IS NULL);'  
    LOOP
        RAISE NOTICE '** % % %', quote_ident(r.table_schema), quote_ident(r.table_name), quote_ident(r.column_name);
    END LOOP;
END LOOP;  
END  
$$;

奥斯瓦尔多

于 2013-07-16T14:31:51.223 回答
2

如果您正在运行 postgresql 9.0+,您可以使用匿名 plpgsql 块来执行一些动态 SQL。

DO $$
DECLARE
    rec         RECORD;
    v_result    INTEGER;
BEGIN
    FOR rec IN 
        SELECT 'select 1 from ' || quote_ident(n.nspname) ||'.'|| quote_ident(c.relname) ||
                    ' where ' || quote_ident(a.attname) || ' IS NULL LIMIT 1' as qry_to_run,
                n.nspname||'.'||c.relname as tbl,
                a.attname as col
        FROM pg_class as c
        INNER JOIN pg_attribute as a ON (a.attrelid = c.oid)
        INNER JOIN pg_type as t ON (t.oid = a.atttypid)
        LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
        WHERE a.attnum >= 1
        AND c.relkind = 'r'
        AND pg_catalog.format_type(a.atttypid, a.atttypmod) = 'boolean'
        AND n.nspname NOT IN ('pg_catalog','information_schema')
        AND a.attnotnull IS NOT TRUE
    LOOP
        EXECUTE rec.qry_to_run INTO v_result;
        IF v_result = 1 THEN
            RAISE NOTICE 'Table % has NULLs in the BOOLEAN field %', rec.tbl,rec.col;
            v_result := 0;
        END IF;
    END LOOP;
END;
$$;
于 2013-07-16T14:55:10.827 回答
2

这推进了@bma 的优秀答案,使其更短、更快、更智能:

DO $$
DECLARE
   rec    record;
  _found  boolean;
BEGIN
   FOR rec IN 
      SELECT format('SELECT TRUE FROM %s WHERE %I IS NULL LIMIT 1'
                   , c.oid::regclass, a.attname) AS qry_to_run
            ,c.oid::regclass AS tbl
            ,a.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 <> 'information_schema'
      AND    n.nspname NOT LIKE 'pg_%'  -- exclude system, temp, toast tbls
      AND    c.relkind = 'r'
      AND    a.attnum > 0
      AND    a.atttypid = 'boolean'::regtype
      AND    a.attnotnull = FALSE
      AND    a.attisdropped = FALSE

   LOOP
      EXECUTE rec.qry_to_run INTO _found;

      IF _found THEN
        RAISE NOTICE 'Table % has NULLs in the BOOLEAN field %'
                    , rec.tbl,rec.col;
      END IF;
   END LOOP;
END
$$;
于 2013-07-16T23:46:43.283 回答