In SQL Server 2008 und gegeben
TableA(A_ID, A_Data)
TableB(B_ID, B_Data)
ViewC(A_or_B_ID, A_or_B_Data)
Ist es möglich, so zu definieren TableZ(A_or_B_ID, Z_Data)
, dass die Z.A_or_B_ID
Spalte auf die in gefundenen Werte beschränkt ist ViewC
? Kann dies mit einem Fremdschlüssel gegen die Ansicht erfolgen?
sql-server
view
foreign-keys
marc
quelle
quelle
In älteren SQL Server-Editionen waren Fremdschlüssel nur über Trigger möglich. Sie können einen benutzerdefinierten Fremdschlüssel nachahmen, indem Sie einen Einfügetrigger erstellen, der prüft, ob der eingefügte Wert auch in einer der relevanten Tabellen angezeigt wird.
quelle
Wenn Sie wirklich brauchen
A_or_B_ID
in TableZ , haben Sie zwei ähnliche Möglichkeiten:1) Fügen Sie der Tabelle z nullable
A_ID
undB_ID
Spalten hinzu,A_or_B_ID
erstellen Sie mit ISNULL eine berechnete Spalte für diese beiden Spalten und fügen Sie eine CHECK-Einschränkung hinzu, sodass nur eine vonA_ID
B_ID
null null ist oder nicht2) Fügen Sie der Tabelle z eine TableName-Spalte hinzu, die entweder A oder B enthalten darf. Erstellen Sie nun
A_ID
undB_ID
als berechnete Spalten, die nur dann nicht null sind, wenn die entsprechende Tabelle benannt wird (unter Verwendung des CASE-Ausdrucks). Machen Sie sie auch hartnäckigIn beiden Fällen haben Sie jetzt
A_ID
undB_ID
Spalten, die geeignete Fremdschlüssel für die Basistabellen haben können. Der Unterschied besteht darin, welche Spalten berechnet werden. Außerdem benötigen Sie in Option 2 oben keinen Tabellennamen, wenn sich die Domänen der 2 ID-Spalten nicht überschneiden - solange Ihr Fallausdruck bestimmen kann, welche DomäneA_or_B_ID
fallen(Danke an den Kommentar zum Korrigieren meiner Formatierung)
quelle
A_or_B_ID
Leider können Sie eine Ansicht in SQL Server nicht mit FK verknüpfen.
quelle
Es gibt noch eine andere Option. Behandeln Sie TableA und TableB als Unterklassen einer neuen Tabelle namens TablePrime. Passen Sie die ID-Werte von TableB so an, dass sie nicht mit den ID-Werten von TableA übereinstimmen. Machen Sie die ID in TablePrime zur PK und fügen Sie alle (angepassten) IDs von TableA und TableB in TablePrime ein. Stellen Sie sicher, dass TableA und TableB auf ihrer PK FK-Beziehungen zu derselben ID in TablePrime haben.
Sie haben jetzt das Supertyp- / Subtyp-Muster und können TablePrime (wenn Sie entweder A oder B möchten ) oder eine der einzelnen Tabellen (wenn Sie nur A oder möchten) einschränken nur B .
Wenn Sie weitere Informationen benötigen, fragen Sie bitte. Es gibt Variationen, mit denen Sie sicherstellen können, dass sich A und B gegenseitig ausschließen, oder dass Sie mit beiden gleichzeitig arbeiten können. Es ist am besten, dies in den FKs zu formalisieren, wenn dies möglich ist.
quelle
Es ist einfacher, eine Einschränkung hinzuzufügen, die auf eine benutzerdefinierte Funktion verweist, die die Prüfung für Sie durchführt: fCheckIfValueExists (columnValue), die true zurückgibt, wenn der Wert vorhanden ist, und false, wenn dies nicht der Fall ist.
Der Vorteil ist, dass es mehrere Spalten empfangen, Berechnungen mit ihnen durchführen, Nullen akzeptieren und Werte akzeptieren kann, die nicht genau einem Primärschlüssel entsprechen, oder mit Ergebnissen von Verknüpfungen verglichen werden kann.
Nachteil ist, dass der Optimierer nicht alle seine Fremdschlüssel-Tricks verwenden kann.
quelle
Entschuldigung, im engeren Sinne des Wortes können Sie keine Fremdschlüssel für Ansichten festlegen. Hier ist warum:
InnoDB ist die einzige integrierte Speicher-Engine für MySQL, die Fremdschlüssel enthält. Jede InnoDB-Tabelle wird in information_schema.tables mit engine = 'InnoDB' registriert.
Ansichten sind zwar in information_schema.tables registriert, verfügen jedoch über eine NULL-Speicher-Engine. In MySQL gibt es keine Mechanismen, um Fremdschlüssel in einer Tabelle mit einer undefinierten Speicher-Engine zu haben.
Vielen Dank!
quelle