使用来自另一个表的序列插入触发器之前的Postgres

时间:2015-03-26 18:30:07

标签: postgresql triggers sql-insert

使用Postgres,我想要实现的是能够拥有许多不同的工具类型,以及相应的[TYPE].instrument表,这些表在表中都有唯一的ID,但也引用了一个唯一的ID。 instrument.master表。我有以下内容:

create schema instrument

CREATE TABLE instrument.type (
    id smallserial NOT NULL,
    name text not null,
    code text not null,
    CONSTRAINT pk_instrument_type PRIMARY KEY (id)
);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_code UNIQUE(code);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_name UNIQUE(name);

insert into instrument.type (name, code) values ('futures', 'f');

CREATE TABLE instrument.master (
    id serial NOT NULL,
    type smallint not null references instrument.type (id),
    timestamp timestamp with time zone not null,
    CONSTRAINT pk_instrument_master PRIMARY KEY (id)
);

CREATE TABLE futures.definition (
    id smallserial NOT NULL,
    code text not null,
    CONSTRAINT pk_futures_definition PRIMARY KEY (id)
);
ALTER TABLE futures.definition ADD CONSTRAINT unq_futures_definition_code UNIQUE(code);

insert into futures.definition (code) values ('ED');

CREATE TABLE futures.instrument (
    id smallserial NOT NULL,
    master serial not null references instrument.master (id),
    definition smallint not null references futures.definition (id),
    month smallint not null,
    year smallint not null,
    CONSTRAINT pk_futures_instrument PRIMARY KEY (id),
    check (month >= 1),
    check (month <= 12),
    check (year >= 1900)
);

ALTER TABLE futures.instrument ADD CONSTRAINT unq_futures_instrument UNIQUE(definition, month, year);

CREATE OR REPLACE FUNCTION trigger_master_futures()
RETURNS trigger AS
$BODY$
BEGIN
    insert into instrument.master (type, timestamp)
    select id, current_timestamp from instrument.type where code = 'f';
    NEW.master := currval('instrument.master_id_seq');

    RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;

create trigger trg_futures_instrument before insert on futures.instrument
for each row
execute procedure trigger_master_futures();

然后我测试:

insert into futures.instrument (definition, month, year)
select id, 3, 2015 from futures.definition where code = 'ED';

一切都像我希望的那样有效。唯一的问题是,不知何故,instrument.master.id最终会超过futures.instrument.master。我不确定我需要做什么来实现我想要的行为,即只要在futures.instrument中插入一个条目,就应该在instrument.master中插入一个条目,id后者的条目应插入前者的master条目中。我实际上认为它应该失败,因为以某种方式违反了外键关系。

1 个答案:

答案 0 :(得分:0)

事实证明,一切都是正确的。问题是在futures.instrument中,主列的类型为serial,它应该是int