【问题标题】:List all tables in Postgres that contain a boolean type column with NULL values?列出 Postgres 中包含具有 NULL 值的布尔类型列的所有表?
【发布时间】:2016-08-05 13:17:16
【问题描述】:

有没有办法列出信息模式中的所有表,这些表包含具有 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 约束。

【问题讨论】:

    标签: postgresql plpgsql dynamic-sql


    【解决方案1】:

    试试:

    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  
    $$;
    

    奥斯瓦尔多

    【讨论】:

    • 奥斯瓦尔多,谢谢您的回复。我更正了循环内的查询: EXECUTE 'SELECT * FROM ' ||报价标识(r.table_name)|| '在哪里' ||报价标识(r.column_name)|| ' 一片空白;'; ,现在它执行了,但没有结果。
    【解决方案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;
    $$;
    

    【讨论】:

    • +1 干得好!我有一些建议,不仅仅是评论,所以我添加了另一个答案。
    【解决方案3】:

    这改进了@bma's excellent answer,使其更短、更快、更智能:

    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
    $$;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2023-03-23
      • 2011-03-02
      相关资源
      最近更新 更多