Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Ein flexibler Fremdschlüssel

Eine Möglichkeit, dies zu lösen, wäre, Ihrer Datenbank eine Tabelle hinzuzufügen, die als Basis für die anderen Tabellen fungiert, und sie mit einer Eins-zu-Eins-Beziehung mit den anderen Tabellen zu verbinden, und dann die Ereignistabelle mit dieser Basistabelle zu verbinden />Auf diese Weise können Sie die Datenintegrität für jede der Tabellen beibehalten.
Die Basistabelle kann so einfach wie nur eine Spalte sein oder Spalten haben, die alle anderen Tabellen gemeinsam haben, wodurch eine Art " Vererbung" in Ihrer Datenstruktur.

Erstellen Sie die Basistabelle (unter der Annahme, dass keine gemeinsamen Spalten zwischen anderen Tabellen vorhanden sind):

CREATE TABLE TblObjectBase 
(
    ObjectBase_Id int IDENTITY(1,1) PRIMARY KEY
)

Dann für jede andere Tabelle, die durch die ObjectId referenziert werden muss in den Events Tabelle:

CREATE TABLE TblClients 
(
    Client_Id int PRIMARY KEY,
    Client_FirstName varchar(10),
    Client_LastName varchar(10),
    --  Other client related data
    CONSTRAINT FK_TblClients_TblObjectBase
               FOREIGN KEY(Client_Id) 
               REFERENCES TblObjectBase(ObjectBase_Id)
)

CREATE TABLE TblInvoices
(
    Invoice_Id int PRIMARY KEY,
    -- other incoice related data
     CONSTRAINT FK_TblInvoices_TblObjectBase
               FOREIGN KEY(Invoice_Id) 
               REFERENCES TblObjectBase(ObjectBase_Id)
)

Das einzige, was bleibt, ist, einen neuen Wert in die TblObjectBase für jede Einfügung in Ihre anderen Tabellen einzufügen. Dies kann einfach durch Stored Procedures oder anstelle von Insert-Triggern erreicht werden.
Eine Insert-Prozedur könnte folgendermaßen aussehen:

CREATE PROCEDURE Insert_TblClients
(
    @Client_FirstName varchar(10),
    @Client_LastName varchar(10),
    -- any other client related data you might have
)
AS
DECLARE @ClientId int

-- Insert a new record to the base table:
INSERT INTO TblObjectBase DEFAULT VALUES;

-- Get the id you've just inserted:
SELECT @ClientId = SCOPE_IDENTITY();

-- Insert the data to the clients table:
INSERT INTO TblClients 
(Client_Id, Client_FirstName, Client_LastName.....) VALUES
(@ClientId, @Client_FirstName, @Client_LastName...)

Ein Statt-Einfüge-Trigger würde so aussehen:

CREATE TRIGGER TblClients_IO_Insert ON TblClients INSTEAD OF INSERT 
AS
BEGIN

DECLARE @ClientId int

-- Insert a new record to the base table:
INSERT INTO TblObjectBase DEFAULT VALUES;

-- Get the id you've just inserted:
SELECT @ClientId = SCOPE_IDENTITY();

INSERT INTO TblClients 
(Client_Id, Client_FirstName, Client_LastName.....) 
SELECT @ClientId, Client_FirstName, Client_LastName..... 
FROM inserted

END

Wenn Sie sich dafür entscheiden, anstelle von insert zu gehen, sollte die Tatsache, dass der Identity-Wert aus einer anderen Tabelle stammt, für den Client (Ihr vb.net-Programm) transparent sein.