Использование правила вставить в последовательность автоинкрементов вторичной таблицы

Для автоматического добавления столбца во второй таблице для связи его с первой таблицей через уникальный индекс у меня есть правило такой следующим образом:

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

Это хорошо работает, если user.userid является целым числом. Однако, если это - последовательность (например, введите последовательный или bigserial), что вставляется в таблицу lastlogin, следующий идентификатор последовательности. Так эта команда:

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');

Первое обходное решение использовало бы тот же идентификатор, и второе обходное решение является всем видом провала.

Действительно ли возможно сделать это через правила postgresql, или я должен просто сделать 2-ю вставку в lastlogin сам или использовать триггер строки? На самом деле я думаю, что триггер строки был бы также автоинкремент последовательность, когда я получаю доступ к NEW.userid.

5
задан A.H. 4 October 2011 в 17:32
поделиться

1 ответ

Forget rules altogether. Они плохие.

Триггеры намного лучше для вас. И в 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)
7
ответ дан 14 December 2019 в 08:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: