如何一次性从PostgreSQL表中删除所有NOT NULL约束

Ste*_*fan 48 sql postgresql constraints notnull sql-drop

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

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

Den*_*rdy 87

您可以在同一个alter语句中对它们进行分组:

alter table tbl alter col1 drop not null,
                alter col2 drop not null,
                …
Run Code Online (Sandbox Code Playgroud)

如果您想编写do块来生成所需的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;
Run Code Online (Sandbox Code Playgroud)

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

如果您这样做,请不要忘记quote_ident()在您需要处理列名中可能奇怪的字符时使用.

  • 您的查询很好。我从来没有查询过目录。尝试使用DO块是我的下一步。 (2认同)

小智 9

ALTER TABLE table_name ALTER COLUMN [SET NOT NULL | DROP NOT NULL]


Pau*_*lgo 8

如果要删除NOT NULLPostreSQL中的所有约束,可以使用此函数:

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;
Run Code Online (Sandbox Code Playgroud)

请注意,主键将被排除在外.

然后你可以用它来调用它:

SELECT dropNull(TABLENAME);


Erw*_*ter 5

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

UPDATE pg_attribute
SET    attnotnull = FALSE
WHERE  attrelid = 'tbl_b'::regclass  -- schema-qualify if needed!
AND    attnotnull
AND    NOT attisdropped
AND    attnum > 0;
Run Code Online (Sandbox Code Playgroud)

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

清洁方式只需要定期的权限更改表:使用动态SQL在其自动化DO声明(这实现什么丹尼斯已经建议):

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
$$
Run Code Online (Sandbox Code Playgroud)

还是非常快的。小心执行动态命令并警惕 SQL 注入。

这是这个更大答案的衍生:
使用 PostgreSQL 9.3 在 CTE UPSERT 中生成默认值

在那里我们需要从创建的表中删除 NOT NULL 约束:

CREATE TABLE tbl_b (LIKE tbl_a INCLUDING DEFAULTS);
Run Code Online (Sandbox Code Playgroud)

因为,根据文档

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