我需要以编程方式删除表的所有约束,而不知道所有约束名称,到目前为止我已经想出了这段代码,其中
'book'
是我想要删除所有约束的表。
DO $$
DECLARE i RECORD;
BEGIN
FOR i IN (SELECT conname
FROM pg_catalog.pg_constraint con
INNER JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid
INNER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace
WHERE rel.relname = 'book') LOOP
EXECUTE format('ALTER TABLE book DROP CONSTRAINT %I', i);
END LOOP;
END $$;
然而,这似乎不仅引用了约束名称(例如
"book_pkey"
),而且还添加了括号("(book_pkey)"
)。或者,这可能是迭代约束名称的问题,尽管单独执行 SELECT
查询会给出所有不带括号或引号的约束的列表:
conname
-----------
book_pkey
(1 row)
执行整个代码块时,Postgres 给出以下错误:
ERROR: constraint "(book_pkey)" of relation "book" does not exist
CONTEXT: SQL statement "ALTER TABLE book DROP CONSTRAINT "(book_pkey)""
PL/pgSQL function inline_code_block line 17 at EXECUTE
对此我能做什么?手动删除括号不可能是正确的答案,不是吗?
这部分是由于在执行语句中使用了%I,当您在格式函数中使用%I时,PostgreSQL会自动在标识符周围添加双引号,以确保将其视为单个区分大小写的实体。通过在格式函数中使用 %s 而不是 %I,您实际上是在告诉 PostgreSQL 不要添加双引号。
DO $$
DECLARE i RECORD;
BEGIN
FOR i IN (SELECT conname
FROM pg_catalog.pg_constraint con
INNER JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid
INNER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace
WHERE rel.relname = 'book') LOOP
EXECUTE format('ALTER TABLE book DROP CONSTRAINT %s', i.conname);
END LOOP;
END $$;
这应该有效。