Règles de PostgreSQL et problème nextval () / serial (très spécifique à PostgreSQL)
Lorsque j'utilise une règle de réécriture qui se fend d'une insertion dans une table en insertions de deux autres tables où l'un de l'insertion des valeurs par défaut nextval('some_sequence') avec le même ordre pour les deux tables, puis l'insertion des valeurs par défaut sont différents dans les deux tables. Ceci est probablement dû à un simple texte de remplacement par la règle de réécriture. J'avais espéré au lieu de la valeur par défaut serait d'abord résolu et puis la même valeur écrite dans les deux tables.
Voici un exemple (comme vous avez pu le deviner, je suis en train de mettre en œuvre de spécialisation/généralisation à l'aide de règles):
-- 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;
Les données spécifiques à l'enfant le premier est conservé dans
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)
);
Ensuite, j'ai défini une vue Enfants1 qui joint les deux tableaux ci-dessus (je l'ai réécrit le point de vue en précisant explicitement que PostgreSQL n'a à définir des vues en fonction de la documentation)
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;
Enfin, la règle de réécriture, je vais avoir des problèmes avec:
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');
);
Essayer d'insérer des données avec
insert into Children1 (attribute1, attribute2)
values ('a1', 'a2'),
('b1', 'b2');
donne le message d'erreur
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".
Un moyen de résoudre ce problème est le remplacement de la deuxième insertion de la règle de réécriture par
insert into Partial_Children1(id, attribute2, type)
select p.id, new.attribute2, p.type
from Parents p
where p.attribute1 = new.attribute1
mais cela repose sur l'unicité de attribut1, je ne veux pas imposer. Une autre solution serait d'insérer les valeurs dans une table temporaire, et ensuite de sélectionner deux fois pour les insertions dans les deux tables. Mais je ne l'aime pas parce que des raisons de performances.
Quelqu'un a une autre idée de la façon d'obtenir les mêmes valeurs par défaut dans les deux tables (juste à l'aide de règles et pas déclencheurs)?
source d'informationauteur j.p. | 2009-08-24
Vous devez vous connecter pour publier un commentaire.
De la documentation
http://www.postgresql.org/docs/8.4/static/rules.html
de sorte qu'il réécrit tout d'abord les requêtes sans l'exécution de quoi que ce soit.
vous pouvez le faire fonctionner lorsque vous n'insérez pas de multipe dossiers à la fois:
Alors vous pouvez faire:
mais pas
Si vraiment vous ne devriez pas utiliser les règles du système avec délicate currval() appelle.
En outre prendre un coup d'oeil sur les commentaires sur ces pages:
Une autre astuce: le soutien à l'postgresql liste de diffusion est aussi excellent que le moteur de base de données elle-même!
Et par la route: faites vos savons que postgresql a un support pour l'héritage out-of-the-box?
Résumé: vous devez utiliser des déclencheurs ou d'éviter de multiples insertions de lignes!
Règles vont le faire pour vous - ils la réécriture de la requête avant de l'exécuter.
Aussi longtemps que vous avez une table réelle de la base (Enfants1), je pense que vous serez en mesure de réaliser la même chose avec un seuil de DÉCLENCHEMENT à la place d'une RÈGLE.