it-swarm.com.de

Wie erstelle ich eine echte Eins-zu-Eins-Beziehung in SQL Server?

Ich möchte eine Eins-zu-Eins-Beziehung in SQL Server 2008 R2 erstellen.

Ich habe zwei Tabellen tableA und tableB. Ich setze den Primärschlüssel von tableB als Fremdschlüssel, der auf den Primärschlüssel von tableA verweist. Wenn ich jedoch die Entity Framework-Datenbank zuerst verwende, ist das Modell 1 bis 0..1.

Jeder weiß, wie man eine echte 1: 1-Beziehung in der Datenbank erstellt?

Danke im Voraus!

32
James

Ich bin ziemlich sicher, dass es in SQL Server technisch unmöglich ist, eine True-1-zu-1-Beziehung zu haben, da dies bedeuten würde, dass Sie mit beide Datensätze gleichzeitig einfügen würden (andernfalls würden Sie einen Einschränkungsfehler erhalten.) insert) in beiden Tabellen, wobei beide Tabellen eine Fremdschlüsselbeziehung zueinander haben.

Das heißt, Ihr mit einem Fremdschlüssel beschriebenes Datenbankdesign ist eine 1 zu 0..1-Beziehung. Es ist keine Einschränkung möglich, die einen Datensatz in tableB erfordern würde. Sie können eine Pseudo-Beziehung mit einem Auslöser haben, der den Datensatz in tableB erstellt. 

Es gibt also einige Pseudo-Lösungen

Speichern Sie zunächst alle Daten in einer einzigen Tabelle. Dann haben Sie keine Probleme mit EF.

Oder zweitens muss Ihre Entität klug genug sein, um keine Einfügung zuzulassen, wenn sie nicht mit einem Datensatz verknüpft ist.

Oder drittens, und höchstwahrscheinlich, Sie haben ein Problem, das Sie lösen möchten, und Sie fragen uns, warum Ihre Lösung nicht funktioniert, anstatt des eigentlichen Problems, das Sie zu lösen versuchen (ein XY-Problem) .

UPDATE

Um in REALITY zu erklären, wie 1 zu 1 Beziehungen nicht funktionieren, verwende ich die Analogie des Chicken- oder Egg-Dilemmas . Ich habe nicht die Absicht, dieses Dilemma zu lösen, aber wenn Sie eine Einschränkung haben sollten, die besagt, dass ein Ei zum Eiertisch hinzugefügt werden muss, muss die Beziehung zwischen dem Huhn und dem Huhn in der Tabelle vorhanden sein Sie können dem Eiertisch kein Ei hinzufügen. Das Gegenteil trifft auch zu. Sie können dem Hühnertisch kein Huhn hinzufügen, wenn sowohl die Beziehung zu dem Ei als auch das Ei in dem Eiertisch vorhanden ist. Es können also keine Datensätze in einer Datenbank erstellt werden, ohne dass eine der Regeln/Einschränkungen verletzt wird.

Die Datenbank Nomenklatur einer Eins-zu-Eins-Beziehung ist irreführend. Alle Beziehungen, die ich gesehen habe (daher meine Erfahrung), wären beschreibender als Eins-zu- (Null oder Eins) -Beziehungen.

45
Erik Philips

Legen Sie den Fremdschlüssel als Primärschlüssel und dann die Beziehung für beide Primärschlüsselfelder fest. Das ist es! Sie sollten ein Schlüsselzeichen an beiden Enden der Beziehungslinie sehen. Dies ist ein Eins zu Eins. 

enter image description here

Überprüfen Sie Folgendes: SQL Server-Datenbankdesign mit einer Eins-zu-Eins-Beziehung

55
Pranay Rana

Dies kann durch Erstellen einer einfachen primären Fremdschlüsselbeziehung und Festlegen der Fremdschlüsselspalte auf folgende Weise erfolgen:

CREATE TABLE [Employee] (
    [ID]    INT PRIMARY KEY
,   [Name]  VARCHAR(50)
);

CREATE TABLE [Salary] (
    [EmployeeID]    INT UNIQUE NOT NULL
,   [SalaryAmount]  INT 
);

ALTER TABLE [Salary]
ADD CONSTRAINT FK_Salary_Employee FOREIGN KEY([EmployeeID]) 
    REFERENCES [Employee]([ID]);

 Schema

INSERT INTO [Employee] (
    [ID]
,   [Name]
)
VALUES
    (1, 'Ram')
,   (2, 'Rahim')
,   (3, 'Pankaj')
,   (4, 'Mohan');

INSERT INTO [Salary] (
    [EmployeeID]
,   [SalaryAmount]
)
VALUES
    (1, 2000)
,   (2, 3000)
,   (3, 2500)
,   (4, 3000);

Überprüfen Sie, ob alles in Ordnung ist

SELECT * FROM [Employee];
SELECT * FROM [Salary];

Im Allgemeinen in Primary Foreign Relationship (Eins zu vielen) können Sie EmployeeID, .__

INSERT INTO [Salary] (
    [EmployeeID]
,   [SalaryAmount]
)
VALUES
    (1, 3000);

Die obige Anweisung zeigt Fehler als

    Violation of UNIQUE KEY constraint 'UQ__Salary__7AD04FF0C044141D'. 
    Cannot insert duplicate key in object 'dbo.Salary'. The duplicate key value is (1).
22
ashim

Es gibt eine Möglichkeit, wie ich eine strikte Eins-zu-Eins-Beziehung erreichen kann, ohne Trigger, berechnete Spalten, zusätzliche Tabellen oder andere "exotische" Tricks (nur Fremdschlüssel und eindeutige Einschränkungen) mit einer kleinen Einschränkung zu verwenden.

Ich werde mir das Chicken-and-the-Egg-Konzept aus der akzeptierten Antwort leihen, um mir zu helfen, die Einschränkung zu erklären.

Es ist eine Tatsache, dass entweder ein Huhn oder ein Ei zuerst kommen muss (in aktuellen DBs sowieso). Glücklicherweise wird diese Lösung nicht politisch und schreibt nicht vor, was zuerst kommen muss - sie überlässt es dem Implementierer.

Der Nachteil ist, dass für die Tabelle, die es ermöglicht, dass ein Datensatz an erster Stelle steht, ein Datensatz ohne den entsprechenden Datensatz in der anderen Tabelle erstellt werden kann. Bei dieser Lösung ist jedoch nur ein solcher Datensatz zulässig. Wenn nur ein Datensatz erstellt wird (nur Hühnchen oder Ei), können zu keiner der beiden Tabellen weitere Datensätze hinzugefügt werden, bis entweder der einsame Datensatz gelöscht wird oder ein übereinstimmender Datensatz in der anderen Tabelle erstellt wird.

Lösung:

Fügen Sie jeder Tabelle Fremdschlüssel hinzu, indem Sie auf die andere Tabelle verweisen, fügen Sie jedem Fremdschlüssel eindeutige Einschränkungen hinzu, und machen Sie einen Fremdschlüssel auf Null, den anderen nicht auf Null und außerdem einen Primärschlüssel. Damit dies funktioniert, darf die eindeutige Einschränkung für die nullfähige Spalte nur eine Null zulassen (dies ist in SQL Server der Fall, andere Datenbanken sind nicht sicher).

CREATE TABLE dbo.Egg (
    ID int identity(1,1) not null,
    Chicken int null,
    CONSTRAINT [PK_Egg] PRIMARY KEY CLUSTERED ([ID] ASC) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE dbo.Chicken (
    Egg int not null,
    CONSTRAINT [PK_Chicken] PRIMARY KEY CLUSTERED ([Egg] ASC) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE dbo.Egg  WITH NOCHECK ADD  CONSTRAINT [FK_Egg_Chicken] FOREIGN KEY([Chicken]) REFERENCES [dbo].[Chicken] ([Egg])
GO
ALTER TABLE dbo.Chicken  WITH NOCHECK ADD  CONSTRAINT [FK_Chicken_Egg] FOREIGN KEY([Egg]) REFERENCES [dbo].[Egg] ([ID])
GO
ALTER TABLE dbo.Egg WITH NOCHECK ADD CONSTRAINT [UQ_Egg_Chicken] UNIQUE([Chicken])
GO
ALTER TABLE dbo.Chicken WITH NOCHECK ADD CONSTRAINT [UQ_Chicken_Egg] UNIQUE([Egg])
GO

Zum Einfügen muss zuerst ein Ei eingefügt werden (mit Null für Chicken). Jetzt kann nur noch ein Huhn eingesetzt werden und es muss sich auf das "nicht beanspruchte" Ei beziehen. Schließlich kann das hinzugefügte Ei aktualisiert werden und es muss sich auf das "nicht beanspruchte" Huhn beziehen. Zu keinem Zeitpunkt können zwei Hühner zum gleichen Ei gemacht werden oder umgekehrt.

Zum Löschen kann dieselbe Logik verwendet werden: Aktualisieren Sie Egg's Chicken auf null, löschen Sie das neu 'nicht beanspruchte' Chicken, und löschen Sie das Ei.

Diese Lösung ermöglicht auch den einfachen Austausch. Interessanterweise könnte das Tauschen das stärkste Argument für die Verwendung einer solchen Lösung sein, da sie potenziell praktisch eingesetzt werden kann. Normalerweise wird in den meisten Fällen eine Eins-zu-Eins-Beziehung von zwei Tabellen besser implementiert, indem einfach die beiden Tabellen in eine Tabelle umgewandelt werden. In einem potenziellen Szenario können die beiden Tabellen jedoch wirklich unterschiedliche Entitäten darstellen, die eine strikte Eins-zu-Eins-Beziehung erfordern, aber häufig 'Partner' austauschen oder im Allgemeinen neu angeordnet werden müssen, während das Eins-Zu-Verhältnis beibehalten wird -eine Beziehung nach der Umgestaltung. Wenn die üblichere Lösung verwendet würde, müssten alle Datenspalten einer der Entitäten für alle neu zuordnenden Paare aktualisiert/überschrieben werden, im Gegensatz zu dieser Lösung, bei der nur eine Spalte mit Fremdschlüsseln neu angeordnet werden muss (die nullfähige Fremdschlüsselspalte).

Nun, dies ist das Beste, was ich mit Standardeinschränkungen tun könnte (nicht beurteilen). Vielleicht wird es jemand nützlich finden.

4
tomosius

1 To 1 Beziehungen in SQL werden durch Zusammenführen des Feldes beider Tabellen in einer erstellt.

Ich weiß, dass Sie eine Tabelle in zwei Entitäten mit einer 1: 1-Beziehung aufteilen können. Die meiste Zeit verwenden Sie diese Option, weil Sie das langsame Laden von "schweren Feldern binärer Daten in einer Tabelle" verwenden möchten. 

Beispiel: Sie haben eine Tabelle, die Bilder mit einer Namensspalte (Zeichenfolge), möglicherweise eine Metadatenspalte, eine Miniaturspalte und das Bild selbst enthält (max). In Ihrer Anwendung werden Sie sicherlich nur den Namen und die Miniaturansicht in einem Collection-Steuerelement anzeigen und dann die "Vollbilddaten" nur dann laden, wenn dies erforderlich ist.

Wenn es das ist, wonach Sie suchen. Es ist etwas, das als "Tischaufteilung" oder "Horizontale Aufteilung" bezeichnet wird.

https://visualstudiomagazine.com/articles/2014/09/01/splitting-tables.aspx

2
Marco Guignard

Dies erreichen Sie am einfachsten, indem Sie nur eine Tabelle mit den Feldern Tabelle A und B (NICHT NULL) erstellen. Auf diese Weise ist es unmöglich, eines ohne das andere zu haben. 

0
Jonathan Nappee

Was ist damit?

create table dbo.[Address]
(
Id int identity not null,
City nvarchar(255) not null,
Street nvarchar(255) not null,
CONSTRAINT PK_Address PRIMARY KEY (Id)
)

create table dbo.[Person]
(
Id int identity not null,
AddressId int not null,
FirstName nvarchar(255) not null,
LastName nvarchar(255) not null,
CONSTRAINT PK_Person PRIMARY KEY (Id),
CONSTRAINT FK_Person_Address FOREIGN KEY (AddressId) REFERENCES dbo.[Address] (Id)
)
0
Muflix