具有未知名称的PostgreSQL丢弃约束

tak*_*eek 6 postgresql dynamic-sql plpgsql psql

我有一个SQL脚本需要删除几个约束并在最后恢复它们,但约束名称是自动生成的,并且每次运行脚本时都会有所不同.

我知道如何从表名中获取约束名称,但似乎不可能在drop语句中使用此信息.

select conname from pg_constraint where
   conrelid = (select oid from pg_class where relname='table name')
   and confrelid = (select oid from pg_class where relname='reference table');
Run Code Online (Sandbox Code Playgroud)

alter table something drop constraint (some subquery) 是语法错误.

理想情况下,我想得到约束名称并将其存储在一个变量中,但似乎Postgres不支持它,我不能使它与psql一起使用\set.

这甚至可能吗?

Erw*_*ter 7

要动态删除和重新创建外键约束,可以将其全部包装在函数中或使用DO命令:

DO
$body$
DECLARE
   _con text := (
      SELECT quote_ident(conname)
      FROM   pg_constraint
      WHERE  conrelid = 'myschema.mytable'::regclass
      AND    confrelid = 'myschema.myreftable'::regclass
      LIMIT 1 -- there could be multiple fk constraints. Deal with it ...
      );

BEGIN
   EXECUTE '
      ALTER TABLE wuchtel12.bet DROP CONSTRAINT ' || _con;

   -- do stuff here

   EXECUTE '
      ALTER TABLE myschema.mytable
      ADD CONSTRAINT ' || _con || ' FOREIGN KEY (col)
      REFERENCES myschema.myreftable (col)';
END
$body$
Run Code Online (Sandbox Code Playgroud)

您必须拥有要使用的表ALTER TABLE.
否则,你可以创建一个函数LANGUAGE plpgsql SECURITY DEFINER(使用相同的体)和

ALTER FUNCTION foo() OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)

postgres作为超级用户 - 或表的所有者.
但一定要知道手册对安全性的看法.

手册中还有更多关于动态命令的内容.