2010-10-26 27 views
2

我有一個非常簡單的表如下所示存儲記錄的作者在文本字段:Postgres的:檢查前值有條件地運行的更新或刪除

CREATE TABLE "public"."test_tbl" (
    "index" SERIAL, 
    "testdate" DATE, 
    "pfr_author" TEXT DEFAULT "current_user"(), 
    CONSTRAINT "test_tbl_pkey" PRIMARY KEY("index"); 

的用戶將不會看到指數或pfr_author字段,但我希望他們能夠更新testdate字段或刪除整個記錄,如果他們有權限並且他們是作者。即如果test_tbl.pfr_author = CURRENT_USER那麼允許更新或刪除,但如果不允許,則會引發錯誤消息,如「對不起,您沒有編輯此記錄的權限」。

我還沒有走下使用觸發器的路線,因爲我認爲即使它在行更新之前執行,用戶請求的更新仍然會在之後發生,無論如何。

我試過這樣做是通過一個規則,但最終與無限遞歸,因爲我把更新命令內的規則。有沒有辦法單獨使用規則或規則和觸發器的組合?

非常感謝您的幫助!

回答

0

在UPDATE和DELETE上使用行級BEFORE觸發器來執行此操作。當操作不被允許並且操作將被跳過時,只要它返回NULL。

http://www.postgresql.org/docs/9.0/interactive/trigger-definition.html

+0

感謝m.m但我想我需要更多的幫助。我在下面構建了觸發器,但是這似乎最終在一個無限遞歸循環中。在觸發器的更新運行之後,是否以某種方式打破循環? – Bannor 2010-10-26 19:50:57

+0

CREATE OR REPLACE FUNCTION 「公」。 「test_tbl_trig_func」() 返回一個觸發器AS $ $身體BEGIN IF (old.pfr_author = 「CURRENT_USER」()或 「CURRENT_USER」()='Postgres的)THEN \t UPDATE test_tbl SET testdate = new。 testdate WHERE「index」= new.index; ELSE NULL; END IF; END; $ body $ LANGUAGE'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 100; CREATE TRIGGER「test_tbl_trig」BEFORE UPDATE ON「public」。「test_tbl」FOR EACH ROW EXECUTE PROCEDURE「public」。「test_tbl_trig_func」(); – Bannor 2010-10-26 19:51:39

+0

EXPLAIN ANALYZE UPDATE test_tbl SET testdate = CURRENT_DATE WHERE test_tbl。「index」= 2;導致:EXPLAIN ANALYZE UPDATE test_tbl SET testdate = CURRENT_DATE WHERE test_tbl。「index」= 2; ... – Bannor 2010-10-26 19:58:31

0

觸發功能有一定的問題,導致遞歸循環update.You應該這樣做:

CREATE OR REPLACE FUNCTION "public"."test_tbl_trig_func"() RETURNS trigger AS $body$ 
BEGIN 
IF not (old.pfr_author = "current_user"() OR "current_user"() = 'postgres') THEN 
    NULL; 
END IF; 
RETURN new; 
END; 
$body$ LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 100; 

我有這樣的測試,它確實很好;

UPDATE test_tbl SET testdate = CURRENT_DATE WHERE test_tbl."index" = 2; 
+0

不錯!你完全改變了方法。不能相信現在有多明顯。 :-) 謝謝! – Bannor 2010-10-27 12:53:04

+0

例如,代碼似乎不起作用,當我用不同的用戶名測試它時,但是這兩個答案一起讓我看到下面的代碼: – Bannor 2010-10-28 23:31:48

+0

CREATE TRIGGER「test_tbl_trig」在更新或刪除之前 ON「public」。「test_tbl」FOR EACH ROW EXECUTE PROCEDURE「public」。「test_tbl_trig_func」(); – Bannor 2010-10-28 23:32:06