PostgreSQL 删除名称未知的约束

问题描述 投票:0回答:2

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

这可能吗?

postgresql plpgsql dynamic-sql psql
2个回答
11
投票

要动态删除和重新创建外键约束,您可以将其全部包装在

FUNCTION
PROCEDURE
(Postgres 11+)或
DO
命令中:

DO
$do$
DECLARE
   /* There could be multiple FK constraints one table to another (even if uncomon).
    * This kind of assignment raises an exception if more than one rows are found:
    * "ERROR:  more than one row returned by a subquery used as an expression"
    * (As opposed to SELECT INTO ...)
    * If that's not what you want, resolve it.
    */
   _con text := (
      SELECT quote_ident(conname)
      FROM   pg_constraint
      WHERE  conrelid = 'myschema.mytable'::regclass      -- source table
      AND    confrelid = 'myschema.myreftable'::regclass  -- FK target table
      );
BEGIN
   IF _con IS NULL THEN
      RAISE EXCEPTION 'FK constraint not found!';  -- flesh out msg ...
   END IF;

   EXECUTE
     'ALTER TABLE myschema.mytable DROP CONSTRAINT ' || _con;

   -- do stuff here

   EXECUTE
     'ALTER TABLE myschema.mytable
      ADD CONSTRAINT ' || _con || ' FOREIGN KEY (col)
      REFERENCES myschema.myreftable (col)';
END
$do$;

执行角色必须拥有要使用的表

ALTER TABLE
(或者是超级用户)。
否则,您可以使用相同的主体创建一个
SECURITY DEFINER
函数
,并且:

ALTER FUNCTION foo() OWNER TO table_owner;

table_owner
是表的所有者(或超级用户)。但请阅读手册中有关安全性的内容

动态命令手册。


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
© www.soinside.com 2019 - 2024. All rights reserved.