Postgresql中插入的条件规则

Postgresql中插入的条件规则,sql,postgresql,conditional,rule,Sql,Postgresql,Conditional,Rule,我的问题与我遇到的postgresql问题有关。 我想修改包含新闻组(如论坛)的数据库。其消息描述一棵树,并存储在如下表中: \d messages Table « public.messages » Column | Type | Modifiers -----------+------------------

我的问题与我遇到的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                     |
(我把输出翻译成法语,希望没有增加误解)

Title是消息标题,datemsg的时间戳、作者和文本非常明确,idgroup是找到消息的讨论组标识符,msgfather是该消息的另一条消息。 我想在insert上实现的规则是防止用户将答案添加到与其父组不同的组的邮件中(如果该组有答案,则新的讨论将以没有父组的新邮件开始)

现在我有这样的看法:

\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);
即使有了这条新规则,人们仍然可以回答一条消息并在另一组中设置此答案

我也试图通过添加
来更改INSU消息规则,其中NEW.msgfather为NULL
,但是当我尝试添加消息时,出现了一个错误,即在newmessage视图中插入时找不到任何规则


那么,如何实现我想做的事情呢?用扳机?(我不知道如何使用postgresql执行此操作)。

首先为
(idmessage,idgroup)
创建一个唯一索引:

下面的
msgfather\u idgroup\u fkey
需要此约束 因为外键约束要求匹配唯一索引和 如果没有它,将出现
错误:对于引用的表“messages”
,没有与给定键匹配的唯一约束

然后添加自引用外键:

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

顺便说一下:

  • notnull
    添加到
    datemsg
    author
    列中


我喜欢你的解决方案,我觉得它非常聪明。我试过了,但不幸的是,我仍然可以回答另一个讨论组的消息。例如,我有一条id=1、idgroup=0的消息,但我仍然可以这样做:
插入到newmessage(title、text、msgfather、idgoup)值('integrity test'、'this message not insert as msgfather not in idgroup 4'、'1'、'4')
。是否可以再次检查此约束是否已成功创建。这应该是不可能的-我已经在我的系统中测试过了。是的,似乎约束没有被创建。这是
\d messages
的输出:我是否应该修改一个现有约束messages\u msgpere\u fkey,它可能与新约束冲突?非常感谢您的回答,我感谢您的帮助。我无法更改表消息添加约束msgfather\u idgroup\fkey外键(msgfather,idgroup)引用消息(idmessage,idgroup)。我有以下错误
错误:«消息»表上的insert或update指令违反外键«msgfather\U idgroup\U fkey»详细信息:«消息»表中不存在键(msgfather,idgroup)=(1,2)。
在添加此约束之前,您首先需要使数据一致。您可以使用
select messages.idmessage from messages left将不一致的记录作为父亲加入到消息中。msgfather=fathers.idmessage where messages.idgroupfathers.idgroup
alter table messages add constraint msgfather_idgroup_fkey
  foreign key (msgfather,idgroup) references messages(idmessage,idgroup);