Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Uma chave estrangeira flexível


Uma maneira de resolver isso seria adicionar uma tabela ao seu banco de dados para atuar como uma base para as outras tabelas e conectá-la com um relacionamento de um para um com as outras tabelas e, em seguida, conectar a tabela de eventos a essa tabela base.
Isso permitirá que você mantenha a integridade dos dados para cada uma das tabelas.
A tabela base pode ser tão simples quanto apenas uma coluna, ou pode ter colunas que todas as outras tabelas tenham em comum, implementando assim uma espécie de " herança" em sua estrutura de dados.

Crie a tabela base (supondo que não haja colunas comuns entre outras tabelas):
CREATE TABLE TblObjectBase 
(
    ObjectBase_Id int IDENTITY(1,1) PRIMARY KEY
)

Então, para qualquer outra tabela que precise ser referenciada pelo ObjectId nos Events tabela:
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)
)

A única coisa que resta é inserir um novo valor no TblObjectBase para qualquer inserção em suas outras tabelas. Isso pode ser facilmente obtido por procedimentos armazenados ou em vez de gatilhos de inserção.
Um procedimento de inserção pode ser assim:
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...)

Um gatilho em vez de inserir ficaria assim:
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 você optar por usar o em vez de inserir, o fato de que o valor Identity vem de outra tabela deve ser transparente para o cliente (seu programa vb.net).