2011-01-12 17 views
0

Ich habe eine Tabelle von Benutzern (Benutzer), und müssen eine neue Tabelle erstellen, um zu verfolgen, welche Benutzer andere Benutzer bezeichnet haben. Ich erstelle also im Grunde eine Viele-zu-Viele-Beziehung zwischen Zeilen in derselben Tabelle.Sql Server-Fehler nicht verstehen

Also ich versuche, Tabelle UserReferrals mit den Spalten UserId und UserReferredId zu erstellen. Ich habe beide Spalten zu einem zusammengesetzten Primärschlüssel gemacht. Und beide Spalten sind Fremdschlüssel, die mit User.UserID verknüpft sind.

Da Löschen eines Benutzers auch die Beziehung löschen sollte, legte ich beide Fremdschlüssel zu kaskadieren löscht. Wenn der Benutzer gelöscht wird, sollten alle zugehörigen Zeilen in UserReferrals ebenfalls gelöscht werden.

Aber das gibt mir die Meldung:

'User' table saved successfully 'UserReferrals' table Unable to create relationship 'FK_UserReferrals_User'. Introducing FOREIGN KEY constraint 'FK_UserReferrals_User' on table 'UserReferrals' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.

ich diesen Fehler nicht erhalten. Ein kaskadierendes Löschen löscht nur die Zeile mit dem Fremdschlüssel, oder? Wie kann es "zyklische Kaskadenpfade" verursachen?

Danke für irgendwelche Tipps.

+0

Sind Sie absolut sicher, dass Sie nicht versehentlich eine der Fremdschlüsseleinschränkungen rückwärts eingerichtet haben? –

+0

Ich habe gerade nochmal nach einem guten Maß gesucht. Beide Spalten zeigen die Benutzertabelle als Primärschlüsseltabelle und UserReferrals als Fremdschlüsseltabelle an. –

Antwort

0

Nachdem darüber nachgedacht, fange ich so viel ist das Problem nicht so sehr in Bezug auf zyklische Kaskade Pfade zu denken, wie es auf mehr Kaskade Pfade in Zusammenhang stehen kann.

Obwohl die beiden UserIDs in meiner Joining-Tabelle immer unterschiedlich sind, verhindert nichts, dass sie identisch sind. Wenn beide auf denselben Benutzer verweisen und dieser Benutzer gelöscht wird, gibt es mehrere Kaskadenpfade zur Verbindungstabelle.

1

Wenn FKs auf einer Tabelle (A) stehen, die auf eine Tabelle (B) verweist, die wiederum eine Beziehung zu (A) hat, oder eine FK, die auf eine PK in derselben Tabelle verweist, kann ein Szenario eingeführt werden wo es umläuft. Manchmal ist dies logisch nicht möglich - aber in der Theorie ist es in den Augen der SQL-Engine möglich.

Dies ist nicht vermeidbar. Typischerweise behandeln wir diese in einem SP (was wir in EF der Delete-Methode zuordnen können).

+0

Könnte ich Sie dazu bringen, zu erläutern, wie ein Fremdschlüssel zyklisch sein kann? Nur die FK Seiten kaskaden, oder? Wie könnte es jemals eine Kaskade zur PK-Seite der Beziehung verursachen? –

+0

Ihre [User] Tabelle hat einen Verweis auf sich selbst über die Beziehung zu [UserReferals] und wieder zurück.Es ist also möglich, dass Benutzer A Benutzer B "referenzieren" könnte und Benutzer B Benutzer A verweisen könnte, was ein zyklisches Kaskadenszenario verursachen würde. Was ich mit der "PK-Seite der Beziehung" meinte, ist, dass wenn die PK auch das Ziel der Beschränkung ist oder die Tabelle sich selbst referenziert. – lukiffer

+0

Tut mir leid, wenn ich es gerade nicht verstehe, aber beide Spalten sind auf der FK-Seite der Beziehung. Daher würde jede Kaskade in der UserReferrals-Tabelle enden. Das heißt, dass keine Löschungen von der FK-Seite der Beziehung her kaskadieren würden, da sie nur von der PK-Seite der Beziehungen her kaskadieren. Kannst du sehen, wo mein Denken schief läuft? –

0

Wenn Sie kaskadierende Löschungen zulassen sollten, würde das Löschen einer Person, deren UserId im Feld UserReferredId anderer Benutzer angezeigt wird, dazu führen, dass diese Benutzer ebenfalls gelöscht werden! Ich vermute, was Sie wollen, ist der Wert von UserReferredId auf null gesetzt, wenn der Benutzer, der mit ihm verbunden ist gelöscht wird.

Es gibt verschiedene Ansätze, die von einem Tabellenauslöser für den Löschbefehl bis zur Verwendung einer Speicherprozedur für das Löschen reichen. Ignoriert der Auslöser böses Argument ist, könnte man so etwas schaffen:

erstellen Trigger clearUserReferredIdOnUserDelete auf Benutzer nach löscht als Update Benutzer gesetzt UserReferredId = null, wo UserReferredId in (wählen Sie Benutzer-ID aus gelöscht)

Die ungetestet ist, aber soll geschlossen sein.

P

+0

Wenn einer der Benutzer gelöscht wird, dann sollten alle Beziehungen, die sie hatten, auch gelöscht werden - nicht auf null gesetzt. Da beide Spalten auf der FK-Seite einer beliebigen Beziehung stehen, kann ich nicht sehen, wie sie dazu führen können, dass etwas anderes gelöscht wird. Sie konnten nur gelöscht werden, wenn eine Zeile in User gelöscht wurde. –