2010-02-12 35 views
4

要在第二臺通過一個唯一索引將它與第一個表自動添加一個專欄中,我有一個規則,例如如下:使用規則插入到輔助表自動遞增序列

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

這工作正常,如果user.userid是一個整數。然而,如果它是一個序列(例如,類型系列bigserial),插入表lastlogin是什麼是下一個序列id。所以這個命令:

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

會插入列[1, '約翰',...]爲用戶但列[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時自動遞增序列。

回答

6

完全忘記規則。他們是不好的

觸發器對你來說更好。而在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; 
 userid | username 
--------+---------- 
     1 | foo 
     2 | bar 
(2 rows) 
select * from lastlogin; 
 userid | lastlogin_time 
--------+---------------- 
     1 | 
     2 | 
(2 rows) 
+1

感謝。觸發器起作用。我很好奇爲什麼規則自動遞增順序而不是觸發器。 – KlaxSmashing

+1

規則是在查詢層面進行的,而不是在數據層面。他們很複雜,很容易做錯。我認爲它們主要用於創建可更新的視圖。 – Tometzky