2013-12-10 60 views
1

我的問題是相對於我遇到的postgresql問題。 我想修改一個包含類新聞組論壇的數據庫。它的消息描述了一棵樹,都存儲在一個表如下:插入Postgresql的條件規則

\d messages 
             Table « public.messages » 
    Column |   Type    |       Modifiers 
-----------+-----------------------------+------------------------------------------------------------------ 
idmessage | integer      | not NULL By default, nextval('messages_idmessage_seq'::regclass) 
title  | character varying(50)  | not NULL 
datemsg | timestamp without time zone | By default, ('now'::text)::timestamp without time zone 
author | character varying(10)  | By default, "current_user"() 
text  | text      | not NULL 
idgroup | integer      | not NULL 
msgfather | integer      | 

(我翻譯自法國的輸出,我希望我沒加誤解)

標題是郵件的標題,datemsg其時間戳,作者和文本都非常明確,idgroup是找到消息的討論組標識符,msgfather是此消息提供的另一個消息。 我想在插入上實現的規則是關於防止用戶添加一個答案給與其父不同的組的消息(如果它有一個,因爲新的討論以沒有父項的新消息開始)。

現在我有這樣的觀點:

\d newmessage 
      View « public.newmessage » 
    Column |   Type   | Modifiers 
-----------+-----------------------+--------------- 
idmessage | integer    | 
title  | character varying(50) | 
text  | text     | 
idgroup | integer    | 
msgfather | integer    | 
View definition : 
SELECT messages.idmessage, messages.title, messages.text, messages.idgroup, messages.msgfather 
    FROM messages; 
Rules : 
ins_message AS 
    ON INSERT TO newmessage DO INSTEAD INSERT INTO messages (title, text, idgroup, msgfather) 
    VALUES (new.title, new.text, new.idgroup, new.msgfather) 

我不能改變視圖或表,因爲人們已經使用的數據庫,所以我覺得我有規則或觸發器玩。

我試圖添加到視圖低於這個規則,沒有預期的效果:

CREATE OR REPLACE RULE ins_message_answer AS ON INSERT TO newmessage WHERE NEW.msgfather IS NOT NULL DO INSTEAD INSERT INTO messages(title, text, idgroup, msgfather) VALUES (NEW.title, NEW.text, (SELECT idgroup FROM messages WHERE idmessage=new.msgfather), NEW.msgfather); 

即使有這種新的規則,人們仍然可以接聽消息,並在另一組設置這個答案。

我也嘗試通過添加WHERE NEW.msgfather IS NULL來更改ins_message規則,但是當我嘗試添加消息時,然後出現在newmessage視圖中沒有找到插入規則的錯誤。

那麼如何實現我想要做的?用觸發器? (我不知道如何用postgresql做一個)。

回答

2

首先創建唯一索引(idmessage, idgroup):需要

alter table messages add constraint messages_idmessage_idgroup_key 
    unique (idmessage, idgroup); 

這種約束對於msgfather_idgroup_fkey以下 爲外鍵約束需要匹配的唯一指標, 沒有它就會有一個ERROR: there is no unique constraint matching given keys for referenced table "messages"

然後添加自參考外鍵:

alter table messages add constraint msgfather_idgroup_fkey 
    foreign key (msgfather,idgroup) references messages(idmessage,idgroup); 

在傳:

+0

我喜歡你的解決方案,我覺得它很聰明。我嘗試過,但不幸的是,我仍然可以在另一個討論組中回覆一條消息。例如,我有一個id = 1,idgroup = 0的消息,但是我仍然可以這樣做:'insert into newmessage(title,text,msgfather,idgoup)values('integrity test','this message should not be inserted作爲msgfather不在idgroup 4','1','4')'。 – Lomanic

+0

您是否可以再次檢查此限制是否已成功創建。它不應該是可能的 - 我已經在我的系統中測試過了。 – Tometzky

+0

是的,似乎約束沒有創建。這裏是'\ d messages'的輸出:http://sebsauvage.net/paste/?5dd1de8e8d74d377#yT3GDcxF/RhAs6HuTQx8q9lVJ3wcSOo7dpbarzoG9LU= 我應該修改現有的約束,messages_msgpere_fkey,這也許就是用新的衝突的一個?非常感謝您的回答,感謝您的幫助。 – Lomanic