Kiedy używam reguły przepisywania, która dzieli wstawkę do jednej tabeli na wstawki do dwóch innych tabel, gdzie jedna z wstawionych wartości ma domyślnie nextval ('some_sequence ') z tą samą sekwencją dla obu tabel, wtedy wstawione wartości domyślne różnią się w dwóch tabelach. Jest to prawdopodobnie spowodowane prostą zamianą tekstu przez regułę przepisywania. Zamiast tego miałem nadzieję, że wartość domyślna zostanie najpierw rozwiązana, a następnie ta sama wartość zostanie zapisana w obu tabelach.Reguły PostgreSQL i nextval()/problem szeregowy (bardzo specyficzny dla PostgreSQL)
Oto przykład (jak zapewne domyślić, próbuję wdrożyć specjalizacji/uogólnienia używając reguł):
-- first and third commands can be skipped if id is defined as serial
create sequence parents_id_seq;
create table Parents(
id integer default(nextval('parents_id_seq')) primary key,
type varchar(50) not null check(type in ('Child1', 'Child2')),
unique (id, type),
attribute1 varchar(50) not null unique check(length(attribute1) > 0)
);
alter sequence parents_id_seq owned by parents.id;
dane specyficzne dla dzieci pierwszego rodzaju są przechowywane w
create table Partial_Children1(
id integer default(nextval('parents_id_seq')) primary key,
type varchar(50) not null check(type = 'Child1'),
foreign key (id, type) references Parents(id, type),
attribute2 varchar(50) not null check(length(attribute2) > 0)
);
Następnie zdefiniowałem widok Children1, który łączy obie powyższe tabele (przepisałem widok, wyraźnie stwierdzając, co PostgreSQL definiuje widoki zgodnie z dokumentacją).
create table Children1(
id int default(nextval('parents_id_seq')),
type varchar(50) not null check(type in ('Child1')),
attribute1 varchar(50) not null check(length(attribute1) > 0),
attribute2 varchar(50) not null check(length(attribute2) > 0)
);
create rule "_RETURN" as on select to Children1 do instead
select p.*, c.attribute2
from Parents p
join Partial_Children1 c
on p.id = c.id;
końcu reguła przepisywania Mam problemy:
create rule ct_i_children1 as
on insert to Children1
do instead (
insert into Parents(attribute1, type)
values(new.attribute1, 'Child1');
insert into Partial_Children1(attribute2, type)
values(new.attribute2, 'Child1');
);
Próbuje wstawić dane z
insert into Children1 (attribute1, attribute2)
values ('a1', 'a2'),
('b1', 'b2');
daje komunikat o błędzie
ERROR: insert or update on table "partial_children1" violates foreign key constraint "partial_children1_id_fkey"
DETAIL: Key (id,type)=(3,Child1) is not present in table "parents".
sposób na rozwiązanie tego zastępuje drugą wstawkę reguły przepisywania przez
insert into Partial_Children1(id, attribute2, type)
select p.id, new.attribute2, p.type
from Parents p
where p.attribute1 = new.attribute1
ale to zależy od wyjątkowości atrybutu1, którego nie chcę narzucać. Innym rozwiązaniem byłoby wstawienie wartości najpierw do tabeli tymczasowej, a następnie dwukrotne wybranie tam wstawień do dwóch tabel. Ale nie podoba mi się to ze względu na wydajność.
Czy ktoś ma inny pomysł, jak uzyskać te same wartości domyślne w obu tabelach (tylko przy użyciu reguł i wyzwalaczy nie)?
Dzięki za linki. Nie rozwiązują problemu, ale przynajmniej nie czuję się już sam ;-). Wbudowane dziedziczenie nie oferowało tego, co chciałem. –