【问题标题】:Using Rule to Insert Into Secondary Table Auto-Increments Sequence使用规则插入辅助表自动增量序列
【发布时间】:2011-01-16 05:42:09
【问题描述】:

要自动在第二个表中添加一列以通过唯一索引将其绑定到第一个表,我有如下规则:

CREATE OR REPLACE RULE auto_insert AS ON INSERT TO user DO ALSO
INSERT INTO lastlogin (id) VALUES (NEW.userid);

如果 user.userid 是一个整数,这可以正常工作。但是,如果它是一个序列(例如,键入 serialbigserial),则插入到表 lastlogin 中的是下一个序列 id。所以这个命令:

INSERT INTO user (username) VALUES ('john');

会将列 [1, 'john', ...] 插入 user,但将列 [2, ...] 插入 lastlogin。以下 2 种解决方法确实有效,但第二种解决方法会消耗两倍的序列,因为序列仍在自动递增:

CREATE OR REPLACE RULE auto_insert AS ON INSERT TO user DO ALSO
INSERT INTO lastlogin (id) VALUES (lastval());

CREATE OR REPLACE RULE auto_insert AS ON INSERT TO user DO ALSO
INSERT INTO lastlogin (id) VALUES (NEW.userid-1);

不幸的是,如果我要插入多行,解决方法将不起作用:

INSERT INTO user (username) VALUES ('john'), ('mary');

第一个解决方法将使用相同的 id,而第二个解决方法则是搞砸了。

是否可以通过 postgresql 规则执行此操作,还是我应该自己第二次插入 lastlogin 或使用行触发器?实际上,我认为当我访问 NEW.userid 时,行触发器也会自动增加序列。

【问题讨论】:

    标签: postgresql rules


    【解决方案1】:

    完全忘记规则。他们是坏的

    触发器对你来说更好。在 99% 的情况下,当有人认为他需要规则时。试试这个:

    create table users (
      userid serial primary key,
      username text
    );
    
    create table lastlogin (
      userid int primary key references users(userid),
      lastlogin_time timestamp with time zone
    );
    
    create or replace function lastlogin_create_id() returns trigger as $$
      begin
        insert into lastlogin (userid) values (NEW.userid);
        return NEW;
      end;
    $$
    language plpgsql volatile;
    
    create trigger lastlogin_create_id
      after insert on users for each row execute procedure lastlogin_create_id();
    

    然后:

    insert into users (username) values ('foo'),('bar');
    
    select * from users;
    
     用户标识 |用户名
    --------+----------
          1 |富
          2 |酒吧
    (2 行)
    
    select * from lastlogin;
    
     用户标识 |上次登录时间
    --------+----------------
          1 |
          2 |
    (2 行)
    

    【讨论】:

    • 谢谢。触发器起作用。我很好奇为什么规则会自动增加序列而不是触发器。
    • 一条规则在查询级别起作用,而不是在数据级别。它们非常复杂且容易出错。我认为它们大多只对创建可更新视图有用。
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    相关资源
    最近更新 更多