2009-07-24 15 views
6

Ciao sto lottando un po 'con questo e potrebbe usare alcune idee ...Record collegati a qualsiasi tabella?

Supponiamo che il mio database abbia le seguenti tabelle; clienti supplers SalesInvoices PurchaseInvoices Valute

etc etc

Mi piacerebbe essere in grado di aggiungere un record di "Notes" a qualsiasi tipo di record

Le note tavolo vorrebbero questo

NoteID  Int (PK) 
NoteFK  Int 
NoteFKType Varchar(3) 
NoteText  varchar(100) 
NoteDate  Datetime 

Dove NoteFK è il PK di un cliente o fornitore ecc. E NoteFKType indica quale tipo di reco la nota è contro

Ora mi rendo conto che non posso aggiungere un FK che fa riferimento a più tabelle senza che NoteFK debba essere presente in tutte le tabelle.

Quindi, come progetteresti quanto sopra? La nota FK ha bisogno di essere in una qualsiasi delle precedenti tabelle

Acclamazioni, Daniel

+0

È richiesta l'integrità referenziale a livello di database o si può vivere con integrità referenziale gestita dall'applicazione? – tschaible

risposta

-2

Perchè non farlo il contrario e hanno una chiave esterna in altre tabelle (cliente, fornitore ecc ecc) per NotesID. In questo modo hai una mappatura uno a uno.

+1

Cosa succede se vuole avere una relazione uno-a-molti? Molte note per un'entità.Si sarebbe concluso con molte tabelle aggiuntive che non sono necessarie. – maciejkow

+1

Ciò non garantisce che lo stesso NoteID non venga referenziato più di una volta. Ma questo dipende dai requisiti aziendali. –

+0

Se ce n'è bisogno per uno a molti, possiamo avere un notesID separati da virgole memorizzati (questa è solo una soluzione alternativa) invece di avere tabelle diverse per il collegamento. –

0

È possibile aggiungere un campo GUID alle tabelle Clienti, Fornitori, ecc. Quindi, nella tabella Note, modificare la chiave esterna per fare riferimento a tale GUID.

Questo non aiuta per l'integrità dei dati. Ma rende le relazioni M-to-N facilmente possibili per qualsiasi numero di tabelle e ti evita di dover definire una colonna NoteFKType nella tabella di Notes.

2

Penso che il tuo progetto sia ok, se puoi accettare il fatto, che il sistema db non controllerà se una nota fa riferimento a un'entità esistente in un'altra tabella o meno. È l'unico disegno che riesco a pensare che non richiede la duplicazione ed è scalabile a più tabelle.

Il modo in cui l'hai progettato, quando aggiungi un altro tipo di entità per cui desideri avere le note, non dovrai modificare il modello. Inoltre, non è necessario includere colonne aggiuntive nel modello esistente o in tabelle aggiuntive.

Per garantire l'integrità dei dati, è possibile creare un set di trigger o una soluzione software che pulirà la tabella delle note di tanto in tanto.

3

È necessario accettare la limitazione che non è possibile insegnare al database in merito a questo vincolo di chiave esterna. Quindi dovrai fare a meno del controllo dell'integrità (e delle eliminazioni a cascata).

Il tuo design è a posto. È facilmente estensibile alle tabelle aggiuntive, è possibile avere più note per entità e le tabelle di destinazione non devono nemmeno essere a conoscenza della funzione delle note.

Un vantaggio che questo progetto ha finito con l'utilizzo di una tabella di note separata per tabella di entità è che è possibile eseguire facilmente le query su tutte le note, ad esempio "note più recenti" o "tutte le note create da un determinato utente".

Per quanto riguarda l'argomento di tale tabella che diventa troppo grande, suddividendolo in cinque tabelle si ridurrà la tabella a circa un quinto della sua dimensione, ma ciò non farà alcuna differenza per l'accesso basato su indice. I database sono costruiti per gestire tabelle grandi (purché siano correttamente indicizzati).

0

È possibile implementare facilmente la chiave "multi" -esterna con i trigger. I trigger ti daranno un meccanismo molto flessibile e potrai fare tutti i controlli di integrità che desideri.

1

Ci penserei due volte prima di fare ciò che suggerisci. Potrebbe sembrare semplice ed elegante a breve termine, ma se sei veramente interessato all'integrità e alle prestazioni dei dati, avere le tabelle delle note separate per ogni tabella genitore è la strada da percorrere. Nel corso degli anni, ho affrontato questo problema utilizzando le soluzioni trovate nelle altre risposte (trigger, GUID, ecc.). Sono giunto alla conclusione che la maggiore complessità e la perdita di prestazioni non ne valgono la pena. Avendo tabelle di note separate per ogni tabella genitore, con vincoli di chiave esterna appropriati, le ricerche e i join saranno semplici e veloci. Quando si combinano gli elementi correlati in una tabella, la sintassi di join diventa brutta e la tabella delle note diventerà enorme e lenta.

+0

+1 Sono d'accordo e posso garantire per questo. A lungo termine stai solo complicando la tua soluzione e aggiungendo debito tecnico che alla fine dovrà essere affrontato. –

+0

D'altra parte, con la sua attuale soluzione può eseguire query su tutte le note, il che sarebbe difficile con più tabelle di note. – Thilo

+1

@Thilo - Con il consiglio di Michael in mente, una vista SQL è un modo più appropriato per aggregare tutte le tabelle di note in una singola origine di query. –

1

Sono d'accordo con Michael McLosky, in una certa misura.

La domanda nella mia mente è: qual è il costo tecnico di avere più tabelle di note?

Nella mia mente, è preferibile consolidare la stessa funzionalità in una singola tabella. Inoltre, rende più semplice la creazione di report e altri sviluppi. Per non parlare di mantenere l'elenco delle tabelle più piccolo e più facile da gestire.

È un atto di equilibrio, è necessario cercare di predeterminare sia i vantaggi che i costi di fare qualcosa di simile. La mia preferenza personale è l'integrità referenziale del database. La gestione dell'applicazione dell'integrità dovrebbe, a mio avviso, essere limitata dalla logica aziendale. La banca dati dovrebbe garantire i dati sono sempre coerenti e valide ...


Per rispondere alla tua domanda in realtà ...

L'opzione che userei è un vincolo di controllo utilizzando un utente definito Funzione per verificare i valori. Funziona in M ​​$ SQL Server ...

CREATE TABLE Test_Table_1 (id INT IDENTITY(1,1), val INT) 
GO 
CREATE TABLE Test_Table_2 (id INT IDENTITY(1,1), val INT) 
GO 
CREATE TABLE Test_Table_3 (fk_id INT, table_name VARCHAR(64)) 
GO 

CREATE FUNCTION id_exists (@id INT, @table_name VARCHAR(64)) 
RETURNS INT 
AS 
BEGIN 
    IF (@table_name = 'Test_Table_1') 
     IF EXISTS(SELECT * FROM Test_Table_1 WHERE id = @id) 
      RETURN 1 
    ELSE 
    IF (@table_name = 'Test_Table_2') 
     IF EXISTS(SELECT * FROM Test_Table_2 WHERE id = @id) 
      RETURN 1 

    RETURN 0 
END 
GO 

ALTER TABLE Test_Table_3 WITH CHECK ADD CONSTRAINT 
    CK_Test_Table_3 CHECK ((dbo.id_exists(fk_id,table_name)=(1))) 
GO 
ALTER TABLE [dbo].[Test_Table_3] CHECK CONSTRAINT [CK_Test_Table_3] 
GO 

INSERT INTO Test_Table_1 SELECT 1 
GO 
INSERT INTO Test_Table_1 SELECT 2 
GO 
INSERT INTO Test_Table_1 SELECT 3 
GO 
INSERT INTO Test_Table_2 SELECT 1 
GO 
INSERT INTO Test_Table_2 SELECT 2 
GO 
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_1' 
GO 
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_2' 
GO 

In questo esempio, l'istruzione di inserimento finale non funzionerà.

1

È possibile ottenere l'integrità referenziale FK, al costo di disporre di una colonna nella tabella delle note per ogni altra tabella.

create table Notes (
    id int PRIMARY KEY, 
    note varchar (whatever), 
    customer_id int NULL REFERENCES Customer (id), 
    product_id int NULL REFERENCES Product (id) 
) 

Quindi è necessario un vincolo per assicurarsi di avere solo una delle colonne impostate.

O forse no, forse è possibile che voglia una nota per poter essere associato sia a un cliente sia a un prodotto. Sta a te.

Questo progetto richiede l'aggiunta di una nuova colonna a Notes se si desidera aggiungere un'altra tabella di riferimento.

+0

Questa è probabilmente la soluzione più elegante finora. – Thilo

Problemi correlati