2012-09-12 61 views
4

我有一個SQL腳本,需要刪除幾個約束並在最後恢復它們,但約束名稱是自動生成的,並且每次腳本運行時都會有所不同。具有未知名稱的PostgreSQL丟棄約束

我知道如何從表名中獲取約束名,但在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工作。

這甚至可能嗎?

+1

您*至少*需要動態SQL來執行此操作。對象名稱(表名,列名等)不能先指定爲變量(或子查詢),而不先構建查詢(以字符串形式),然後執行該查詢。使用sed/awk在文件中生成「DROP xxx」行,並通過psql管理該文件可能是一種解決方法。它仍然很難保持一些「原子性」(但DDL在這方面總是很困難) – wildplasser

+0

@wildplasser好吧,我想也許psql會有一些功能來做到這一點。否則,你可以把你的評論作爲答案。 – takteek

+0

我不是那麼隨意動態查詢建築物(其實我討厭它)其他人可能會填充它。 – wildplasser

回答

6

要動態下降&重建一個外鍵約束,你可以把它包裝都在一個功能或使用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表。
你還能create a functionLANGUAGE plpgsql SECURITY DEFINER(使用相同的體)和

ALTER FUNCTION foo() OWNER TO postgres; 

postgres在這裏是超級用戶 - 或表的所有者。
但是一定要知道什麼the manual has to say about security

The manual also has more on dynamic commands.