Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Una chiave esterna flessibile

Un modo per risolverlo sarebbe aggiungere una tabella al database che funga da base per le altre tabelle e collegarla con una relazione uno a uno con le altre tabelle, quindi collegare la tabella degli eventi a questa tabella di base.
Ciò ti consentirà di mantenere l'integrità dei dati per ciascuna delle tabelle.
La tabella di base può essere semplice come una sola colonna o può avere colonne comuni a tutte le altre tabelle, implementando così una sorta di " ereditarietà" nella struttura dei dati.

Crea la tabella di base (supponendo che non ci siano colonne comuni tra le altre tabelle):

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

Quindi, per qualsiasi altra tabella che deve essere referenziata da ObjectId negli Events tabella:

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)
)

L'unica cosa rimasta è inserire un nuovo valore in TblObjectBase per qualsiasi inserimento nelle altre tabelle. Questo può essere facilmente ottenuto tramite stored procedure o invece di trigger di inserimento.
Una procedura di inserimento potrebbe essere simile a questa:

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...)

Un trigger invece di inserimento sarebbe simile a questo:

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

Se scegli di utilizzare invece di inserire, il fatto che il valore Identity provenga da un'altra tabella dovrebbe essere trasparente per il client (il tuo programma vb.net).