5

2 番目のテーブルに列を自動的に追加して、一意のインデックスを介して最初のテーブルに関連付けるには、次のようなルールがあります。

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

user.useridが整数の場合、これは正常に機能します。ただし、シーケンスの場合 (たとえば、タイプserialまたはbigserial )、テーブルlastloginに挿入されるのは、次のシーケンス ID です。したがって、このコマンド:

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

列 [1, 'john', ...] をuserに挿入しますが、列 [2, ...] をlastloginに挿入します。次の 2 つの回避策は機能しますが、2 番目の回避策では、シーケンスがまだ自動インクリメントされているため、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 を使用し、2 番目の回避策はあらゆる種類の失敗です。

postgresqlルールを介してこれを行うことは可能ですか、それともlastloginへの2回目の挿入を自分で行うか、行トリガーを使用する必要がありますか? 実際、 NEW.useridにアクセスすると、行トリガーもシーケンスを自動インクリメントすると思います。

4

1 に答える 1

7

ルールを完全に忘れてください。彼らは悪いです。

トリガーはあなたにとってはるかに優れています。そして、誰かがルールが必要だと思う場合の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;
ユーザー ID | ユーザー名
------+----------
      1 | ふー
      2 | バー
(2行)
select * from lastlogin;
ユーザー ID | lastlogin_time
------+----------------
      1 |
      2 |
(2行)
于 2010-02-12T17:06:19.850 に答える