webentwicklung-frage-antwort-db.com.de

Kann ich einen Fremdschlüssel haben, der auf eine Spalte in einer Ansicht in SQL Server verweist?

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, TableZ(A_or_B_ID, Z_Data) so zu definieren, dass die Spalte Z.A_or_B_ID auf die Werte in ViewC beschränkt ist? Kann dies mit einem Fremdschlüssel gegen die Ansicht erfolgen?

81
marc

Sie können nicht auf eine Ansicht in einem Fremdschlüssel verweisen.

101
Brian Fisher

In älteren SQL Server-Editionen waren Fremdschlüssel nur über Trigger möglich. Sie können einen benutzerdefinierten Fremdschlüssel imitieren, indem Sie einen Insert-Trigger erstellen, der prüft, ob der eingefügte Wert auch in einer der relevanten Tabellen angezeigt wird.

24
lorin_f

Wenn Sie wirklich brauchen A_or_B_ID In TableZ haben Sie zwei ähnliche Optionen:

1) Add nullable A_ID und B_ID Spalten zu Tabelle z, machen A_or_B_ID eine berechnete Spalte, in der ISNULL für diese beiden Spalten verwendet wird, und fügen Sie eine CHECK-Einschränkung hinzu, sodass nur eine von A_ID oder B_ID ist nicht null

2) Fügen Sie der Tabelle z eine TableName-Spalte hinzu, die entweder A oder B enthalten darf. Jetzt erstellen Sie A_ID und B_ID als berechnete Spalten, die nur dann ungleich Null sind, wenn ihre entsprechende Tabelle benannt ist (unter Verwendung des CASE-Ausdrucks). Lassen Sie sie auch bestehen

In beiden Fällen haben Sie jetzt A_ID und B_ID Spalten, die entsprechende Fremdschlüssel zu den Basistabellen haben können. Der Unterschied besteht darin, in welchen Spalten berechnet wird. Außerdem benötigen Sie in Option 2 oben keinen Tabellennamen, wenn sich die Domänen der 2 ID-Spalten nicht überlappen - vorausgesetzt, Ihr case-Ausdruck kann bestimmen, welche Domäne A_or_B_ID fällt in

(Danke an den Kommentar zum Korrigieren meiner Formatierung)

15

Es tut uns leid, Sie können nicht zu einer Ansicht in SQL Server FK.

8
Jarrett Meyer

Es gibt noch eine andere Option. Behandeln Sie TableA und TableB als Unterklassen einer neuen Tabelle mit dem Namen 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 Supertype/Subtype-Muster und können Einschränkungen für TablePrime (wenn Sie möchten entweder-A-oder-B) oder eine der einzelnen Tabellen (wenn Sie möchten nur A) festlegen oder nur B).

Wenn Sie weitere Informationen benötigen, fragen Sie bitte. Es gibt Variationen, mit denen Sie sicherstellen können, dass A und B sich gegenseitig ausschließen, oder vielleicht kann das, mit dem Sie arbeiten, beides gleichzeitig sein. Es ist am besten, dies in den FKs zu formalisieren, wenn dies möglich ist.

4
ErikE

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.

Views, die in information_schema.tables registriert sind, verfügen ü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!

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) gibt true zurück, wenn der Wert vorhanden ist, und false, wenn dies nicht der Fall ist.

Der Vorteil ist, dass mehrere Spalten empfangen, Berechnungen mit ihnen durchgeführt, Nullen akzeptiert und Werte akzeptiert werden können, die nicht genau einem Primärschlüssel entsprechen oder mit den Ergebnissen von Verknüpfungen verglichen werden können.

Nachteil ist, dass der Optimierer nicht alle seine Fremdschlüssel-Tricks anwenden kann.

1
Camilo J