2009-07-27 19 views
21

Sto definendo un database per un cliente/sistema di ordini in cui ci sono due tipi distinti di clienti. Perché sono così diversi che avere una sola tabella clienti sarebbe molto brutta (sarebbe piena di colonne nulle perché sono inutili per un tipo).Più chiavi esterne a una singola colonna

I loro ordini sono nello stesso formato. È possibile avere una colonna CustomerId nella mia tabella degli ordini che ha una chiave esterna per entrambi i tipi di clienti? L'ho configurato su SQL server e non mi hanno dato problemi creando le relazioni, ma devo ancora provare a inserire i dati.

Inoltre, sto pianificando di utilizzare nHibernate come ORM, potrebbero esserci dei problemi introdotti effettuando le relazioni in questo modo?

risposta

19

No, non è possibile avere un singolo campo come chiave esterna per due tabelle diverse. Come diresti dove cercare la chiave?

Avresti almeno bisogno di un campo che indichi che tipo di utente sia, o due chiavi esterne separate.

È inoltre possibile inserire le informazioni comuni a tutti gli utenti in una tabella e disporre di tabelle separate per le informazioni specifiche per i tipi di utente, in modo da disporre di un'unica tabella con ID utente come chiave primaria.

+1

D'accordo. La normalizzazione è la chiave qui. – jva

+1

@Guffa: -1 perché "No, non è possibile avere un singolo campo come chiave esterna a due tabelle diverse": questa istruzione non è corretta (almeno su SQL Server 2005). Dagli un giro. – Liao

+2

@Liao: Non penso che tu capisca la situazione ... Se per esempio hai il valore della chiave esterna 42, come faresti a sapere se è la chiave nella tabella A o nella tabella B? – Guffa

3

Una chiave esterna può fare riferimento a una sola chiave primaria, quindi no. Tuttavia, è possibile utilizzare un tavolo da bridge:

CustomerA <---- CustomerA_Orders ----> Order 
CustomerB <---- CustomerB_Orders ----> Order 

Quindi Ordine non nemmeno hanno una chiave esterna; se questo è desiderabile, però ...

1

È possibile creare una chiave esterna facendo riferimento a più tabelle. Questa funzione consente di partizionare verticalmente la tabella e mantenere l'integrità referenziale. Nel tuo caso, tuttavia, questo non è applicabile.

La soluzione migliore sarebbe disporre di una tabella CustomerType con possibili colonne: CustomerTypeID, CustomerID, dove CustomerID è il PK e quindi rinviare la tabella OrderID a CustomerID.

Raj

0

due tipi distinti di clienti è un classico caso di tipi e sottotipi o, se si preferisce, classi e sottoclassi. Here è una risposta da un'altra domanda.

In sostanza, la tecnica dell'ereditarietà delle tabelle di classe è come la risposta di Arnand. L'uso della tecnica della chiave primaria condivisa è ciò che consente di aggirare i problemi creati da due tipi di chiave esterna in una colonna. La chiave esterna sarà id cliente. Questo identificherà una riga nella tabella clienti e anche una riga nel tipo appropriato di tabella tipo cliente, a seconda dei casi.

0

Come indicato, se la chiave è, ad esempio, 12345, come sapresti in quale tabella cercare? Potresti, suppongo, fare qualcosa per assicurare che i valori chiave per le due tabelle non si sovrappongano mai, ma questo è troppo brutto e doloroso da contemplare. Potresti avere un secondo campo che dice quale tipo di cliente è. Ma se hai due campi, perché non avere un campo per l'id del tipo di cliente 1 e un altro per l'id del tipo di cliente 2.

Senza sapere di più sulla tua app, il mio primo pensiero è che dovresti avere una tabella generale dei clienti con i dati che sono comuni a entrambi, e quindi avere due tabelle aggiuntive con i dati specifici per ogni tipo di cliente.Penso che ci debbano essere molti dati comuni a due cose fondamentali come il nome e l'indirizzo e il numero del cliente almeno - e le ripetute colonne tra tabelle fanno schifo. Le tabelle aggiuntive potrebbero quindi fare riferimento alla tabella di base. Poiché esiste una sola chiave per la tabella di base, il problema delle chiavi esterne deve sapere a quale tabella fare riferimento evapora.

1

Ho ereditato un database SQL Server in cui è stato eseguito (una singola colonna utilizzata in quattro relazioni di chiavi esterne con quattro tabelle non correlate), quindi sì, è possibile. Il mio predecessore è sparito, però, quindi non posso chiedere perché ha pensato che fosse una buona idea.

Ha utilizzato una colonna GUID (tipo "uniqueidentifier") per evitare il problema dell'ambiguità e ha disattivato il controllo dei vincoli sulle chiavi esterne, poiché è garantito che ne corrisponda solo uno. Ma posso pensare a molte ragioni che non dovresti, e non ho pensato a nessuna ragione per cui dovresti.

Il tuo suona come il classico problema di "specializzazione", in genere risolto creando una tabella padre con i dati cliente condivisi, quindi due tabelle figlio che contengono i dati univoci per ogni classe di clienti. La tua chiave esterna sarebbe quindi contro la tabella dei clienti principali e la tua determinazione del tipo di cliente sarebbe basata su quale tabella figlio aveva una voce corrispondente.

0
  1. Creare una tabella "cliente" include tutte le colonne che hanno gli stessi dati per entrambi i tipi di cliente.
  2. che creare tabella "customer_a" e "customer_b"
  3. Usa "customer_id" da tavolo "consumatore" come chiave esterna in "customer_a" e "customer_b"

       customer 
            | 
        --------------------------------- 
        |        | 
    cusomter_a      customer_b 
    
Problemi correlati