8

我有一个 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');

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

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

这甚至可能吗?

4

2 回答 2

9

要动态删除和重新创建外键约束,您可以将其全部包装在一个函数中或使用以下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$

您必须拥有该表才能使用ALTER TABLE
否则,您可以使用(使用LANGUAGE plpgsql SECURITY DEFINER相同的主体)和

ALTER FUNCTION foo() OWNER TO postgres;

postgres作为这里的超级用户 - 或表的所有者。
但请务必了解手册中有关安全性的内容

该手册还有更多关于动态命令的内容。

于 2012-09-12T21:55:20.930 回答
0

您也可以使用存储过程。

CREATE OR REPLACE PROCEDURE public.p_costraint()
 LANGUAGE plpgsql
AS $procedure$
DECLARE _constrint text;
begin
-- for dynamic change the constraint. 
    _constrint := (
      SELECT quote_ident(conname)
      FROM   pg_constraint
        WHERE  conrelid = 'test.contacts'::regclass
        AND    confrelid = 'test.customers'::regclass
      LIMIT 1 -- there could be multiple fk constraints. Deal with it ...
      );
    _constrint := _constrint || 'test';
    EXECUTE '
      ALTER TABLE test.contacts
      ADD CONSTRAINT ' || _constrint || ' FOREIGN KEY (customer_id)
      REFERENCES test.customers (customer_id)';
    RAISE NOTICE 'hello, world!';
end
$procedure$;

在这里。约束名称用作文本变量。
您可以直接调用它:call public.p_costraint();
它将返回:

NOTICE:  hello, world!
CALL
于 2021-12-14T10:21:07.653 回答