J'ai rencontré des problèmes de modélisation d'un schéma électrique dans SQL. La structure que j'aimerais capturer est
part ←────────── pin
↑ ↑
part_inst ←───── pin_inst
où "inst" est court pour "instance".
Par exemple, j'aurais peut-être en tant que part
un ampli OP-LM358 avec pin
s 1out, 1in- 1in +, GND, 2in +, 2in, 2OUT et VCc. Je pourrais alors placer cette partie sur un schéma, créant un part_inst
et 8 pin_inst
s.
Ignorer les champs de données, ma tentative initiale d'un schéma était
create table parts (
part_id bigserial primary key
);
create table pins (
pin_id bigserial primary key,
part_id bigint not null references parts
);
create table part_insts (
part_inst_id bigserial primary key,
part_id bigint not null references parts
);
create table pin_insts (
pin_inst_id bigserial primary key,
part_inst_id bigint not null references part_insts,
pin_id bigint not null references pins
);
Le principal problème avec ce schéma est qu'un pin_inst
peut être attaché à un part_inst
avec part_id=1
mais son pin
a part_id=2
.
J'aimerais éviter ce problème sur le niveau de la base de données plutôt que le niveau d'application. Donc, j'ai modifié mes principales clés pour appliquer cela. J'ai marqué les lignes changées avec --
.
create table parts (
part_id bigserial primary key
);
create table pins (
pin_id bigserial, --
part_id bigint not null references parts,
primary key (pin_id, part_id) --
);
create table part_insts (
part_inst_id bigserial, --
part_id bigint not null references parts,
primary key (part_inst_id, part_id) --
);
create table pin_insts (
pin_inst_id bigserial primary key,
part_inst_id bigint not null, --
pin_id bigint not null, --
part_id bigint not null references parts, --
foreign key (part_inst_id, part_id) references part_insts, --
foreign key (pin_id, part_id) references pins --
);
Ma gripe avec cette méthode est qu'elle pollue les clés primaires: partout où je me réfère à un part_inst
, J'ai besoin de garder une trace de l'part_inst_id
et le part_id
. Y a-t-il une autre façon de faire de l'application de la contrainte pin_inst.part_inst.part_id = pin_inst.pin.part_id
Sans être trop verbeux?
Une solution radicale peut être de supprimer pin_inst
complètement:
part ←────────── pin
↑ ↑
part_inst ←───── pin_inst
Vous n'avez rien dans votre question pour vous suggérer que vous avez réellement besoin de la table redondante. Pour pin
s associé à un part_inst
, regarde le pin
s de l'associé part
.
Cela simplifierait le code à:
create table part ( -- using singular terms for table names
part_id bigserial primary key
);
create table pin (
pin_id bigserial primary key,
part_id bigint not null references part
);
create table part_inst (
part_inst_id bigserial primary key,
part_id bigint not null references part
);
Mais votre commentaire a clairement précisé que nous ne vous échapperons pas avec ça ...
pin_inst
est nécessaireComprenant part_id
Comme vous l'avez fait est la solution la plus simple avec des contraintes de clé étrangère. Vous ne pouvez pas faire référence à une table "Deux tables" "avec contraintes de clé étrangère .
Mais vous pouvez au moins faire faire sans "polluer" les clés primaires. Ajouter UNIQUE
contraintes .
create table part (
part_id bigserial primary key
);
create table pin (
pin_id bigserial primary key,
part_id bigint not null references part,
unique(part_id, pin_id) -- note sequence of columns
);
create table part_inst (
part_inst_id bigserial primary key,
part_id bigint not null references part,
unique(part_id, part_inst_id)
);
create table pin_inst (
pin_inst_id bigserial primary key,
part_inst_id bigint not null,
pin_id bigint not null,
part_id bigint not,
foreign key (part_id, pin_id) references pin,
foreign key (part_id, part_inst_id) references part_inst
);
Je mets part_id
Tout d'abord dans les contraintes uniques. Cela n'est pas pertinent pour l'intégrité référentielle, mais cela compte pour la performance. Les touches principales appliquent déjà des index pour les colonnes PK. Il vaut mieux avoir le Autre colonne d'abord dans les index multicolumnistes mettant en œuvre les contraintes uniques. Détails dans ces questions connexes:
Questions connexes sur SO:
Vous pourriez avoir recours aux fonctions des déclencheurs, qui sont plus flexibles, mais un peu plus compliqué et sujet aux erreurs et un peu moins strict. L'avantage: vous pourriez faire sans part_inst.part_id
et pin.part_id
...