Ich hatte Probleme beim Modellieren eines elektrischen Schaltplans in SQL. Die Struktur, die ich erfassen möchte, ist
part ←────────── pin
↑ ↑
part_inst ←───── pin_inst
Dabei steht "inst" für "instance".
Zum Beispiel könnte ich als part
LM358 Operationsverstärker mit pin
s 1OUT, 1IN-, 1IN +, GND, 2IN +, 2IN-, 2OUT und V CC haben . Ich könnte diesen Teil dann auf einen Schaltplan setzen und a part_inst
und 8
pin_inst
s erstellen .
Ich ignorierte Datenfelder und versuchte zunächst, ein Schema zu erstellen
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
);
Das Hauptproblem bei diesem Schema ist, dass a pin_inst
möglicherweise an a part_inst
mit gebunden ist, part_id=1
aber es pin
hat part_id=2
.
Ich möchte dieses Problem eher auf Datenbankebene als auf Anwendungsebene vermeiden. Also habe ich meine Primärschlüssel geändert, um dies durchzusetzen. Ich habe die geänderten Zeilen mit markiert --
.
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 --
);
Mein Problem mit dieser Methode ist, dass sie die Primärschlüssel verschmutzt: Überall, wo ich auf a verweise, part_inst
muss ich sowohl das part_inst_id
als auch das verfolgen
part_id
. Gibt es eine andere Möglichkeit, die Einschränkung durchzusetzen,
pin_inst.part_inst.part_id = pin_inst.pin.part_id
ohne übermäßig ausführlich zu sein?
quelle
pin_inst_id
Redundanz entfernen . Sie können den(part_inst_id, part_id, pin_id)
als Primärschlüssel verwenden.Antworten:
Minimale Lösung
Eine radikale Lösung könnte darin bestehen, sie
pin_inst
vollständig zu entfernen :Ihre Frage enthält nichts, was darauf hindeutet, dass Sie die redundante Tabelle tatsächlich benötigen. Schauen Sie sich für
pin
s, die mit a verknüpft sindpart_inst
, daspin
s des zugeordneten s anpart
.Das würde den Code vereinfachen, um:
Aber Ihr Kommentar hat deutlich gemacht, dass wir damit nicht durchkommen werden ...
Alternative, wenn
pin_inst
nötigEinschließen
part_id
wie Sie ist die einfachste Lösung mit Fremdschlüsseleinschränkungen. Sie können nicht auf eine Tabelle "zwei Tabellen entfernt" mit Fremdschlüsseleinschränkungen verweisen .Aber Sie können zumindest auskommen, ohne die Primärschlüssel zu "verschmutzen". Fügen Sie
UNIQUE
Einschränkungen hinzu .Ich stelle
part_id
zuerst die einzigartigen Einschränkungen ein. Das ist für die referenzielle Integrität irrelevant, aber für die Leistung von Bedeutung. Die Primärschlüssel implementieren bereits Indizes für die pk-Spalten. Es ist besser, die andere Spalte zuerst in den mehrspaltigen Indizes zu haben, um die eindeutigen Einschränkungen zu implementieren. Details unter diesen verwandten Fragen:Verwandte Fragen zu SO:
Alternative mit Triggern
Sie könnten auf Triggerfunktionen zurückgreifen, die flexibler, aber etwas komplizierter und fehleranfälliger und etwas weniger streng sind. Der Vorteil: Sie könnten ohne
part_inst.part_id
undpin.part_id
...quelle
pin_insts
, die ich jedoch aus Gründen der Lesbarkeit weggelassen habe ("Datenfelder ignorieren, [...]"). Beispielsweise kann apin_inst
als Eingabe oder Ausgabe markiert werden.