【问题标题】:How to drop all NOT NULL constraints from a PostgreSQL table in one go如何一次性从 PostgreSQL 表中删除所有 NOT NULL 约束
【发布时间】:2013-12-07 10:17:10
【问题描述】:

是否可以一次性从表中删除所有 NOT NULL 约束?

我有一个包含很多 NOT NULL 约束的大表,我正在寻找一种比单独删除它们更快的解决方案。

【问题讨论】:

标签: sql postgresql constraints sql-drop notnull


【解决方案1】:

您可以将它们全部分组在同一个 alter 语句中:

alter table tbl alter col1 drop not null,
                alter col2 drop not null,
                …

如果您想编写do block 来生成所需的sql,也可以从目录中检索相关列的列表。例如,类似:

select a.attname
  from pg_catalog.pg_attribute a
 where attrelid = 'tbl'::regclass
   and a.attnum > 0
   and not a.attisdropped
   and a.attnotnull;

(请注意,这也将包括与主键相关的字段,因此您需要将它们过滤掉。)

如果您这样做,请不要忘记使用quote_ident(),以防您需要处理列名中可能出现的奇怪字符。

【讨论】:

  • 您的查询很棒。我从来没有查询过目录。尝试 DO 块将是我的下一步。
【解决方案2】:

ALTER TABLE 表名 ALTER COLUMN [SET NOT NULL|删除非空]

【讨论】:

    【解决方案3】:

    如果你想在 PostreSQL 中删除所有 NOT NULL 约束,你可以使用这个函数:

    CREATE OR REPLACE FUNCTION dropNull(varchar) RETURNS integer AS $$
    DECLARE
      columnName varchar(50);
    BEGIN
    
        FOR columnName IN  
    
    select a.attname
      from pg_catalog.pg_attribute a
     where attrelid = $1::regclass
       and a.attnum > 0
       and not a.attisdropped
       and a.attnotnull and a.attname not in(
    
       SELECT               
      pg_attribute.attname
    FROM pg_index, pg_class, pg_attribute 
    WHERE 
      pg_class.oid = $1::regclass AND
      indrelid = pg_class.oid AND
      pg_attribute.attrelid = pg_class.oid AND 
      pg_attribute.attnum = any(pg_index.indkey)
      AND indisprimary)
    
              LOOP
              EXECUTE 'ALTER TABLE ' || $1 ||' ALTER COLUMN '||columnName||' DROP NOT NULL';        
            END LOOP;
        RAISE NOTICE 'Done removing the NOT NULL Constraints for TABLE: %', $1;
        RETURN 1;
    END;
    $$ LANGUAGE plpgsql;
    

    请注意,主键将被排除。

    然后你可以调用它:

    选择 dropNull(TABLENAME);

    【讨论】:

      【解决方案4】:

      有一种快速而肮脏的方式具有超级用户权限

      UPDATE pg_attribute
      SET    attnotnull = FALSE
      WHERE  attrelid = 'tbl_b'::regclass  -- schema-qualify if needed!
      AND    attnotnull
      AND    NOT attisdropped
      AND    attnum > 0;
      

      捷径很诱人。但如果你搞砸了,你最终可能会破坏你的系统。
      基本规则是:永远不要直接篡改系统目录。

      干净的方式只需要常规权限来更改表:在 DO 语句中使用动态 SQL 将其自动化(这实现了 what Denis already suggested):

      DO
      $$
      BEGIN
      
      EXECUTE (
         SELECT 'ALTER TABLE tbl_b ALTER '
             || string_agg (quote_ident(attname), ' DROP NOT NULL, ALTER ')
             || ' DROP NOT NULL'
         FROM   pg_catalog.pg_attribute
         WHERE  attrelid = 'tbl_b'::regclass
         AND    attnotnull
         AND    NOT attisdropped
         AND    attnum > 0
         );
      
      END
      $$
      

      仍然非常快。谨慎执行动态命令,谨防 SQL 注入。

      这是从这个更大的答案中衍生出来的:
      Generate DEFAULT values in a CTE UPSERT using PostgreSQL 9.3

      我们需要从使用以下方法创建的表中删除 NOT NULL 约束:

      CREATE TABLE tbl_b (LIKE tbl_a INCLUDING DEFAULTS);
      

      因为,per documentation

      非空约束总是被复制到新表中。

      【讨论】:

        【解决方案5】:

        我有一个场景需要从整个数据库中具有特定名称的每个字段中删除 NOT NULL。这是我的解决方案。可以修改 where 子句以处理您需要的任何搜索模式。

        DO $$ DECLARE row record;
        BEGIN FOR row IN 
            (
                SELECT
                    table_schema, table_name, column_name
                FROM
                    information_schema.columns 
                WHERE
                    column_name IN ( 'field1', 'field2' )
            )
            LOOP
                EXECUTE 
                  'ALTER TABLE ' || row.table_schema || '.' || row.table_name || ' ALTER '
               || string_agg (quote_ident(row.column_name), ' DROP NOT NULL, ALTER ')
               || ' DROP NOT NULL;';
            END LOOP;
        END; $$;
        

        借鉴了其他一些示例,这更适合我的需求

        【讨论】:

          【解决方案6】:

          是的,是的。我也有同样的问题。。

          要解决这个问题,我必须编写一个 C# .net 脚本,它遍历所有 plSql 数据库并删除所有匹配的约束..

          有关如何删除单个约束的具体信息,请点击链接。 http://www.techonthenet.com/oracle/foreign_keys/drop.php

          【讨论】:

            猜你喜欢
            • 2023-03-11
            • 1970-01-01
            • 2016-09-19
            • 2015-09-25
            • 1970-01-01
            • 2022-01-26
            • 2021-03-04
            • 2012-09-17
            相关资源
            最近更新 更多