2010-02-18 19 views
5

Ho le seguenti tabelle nel server MySQL:Come far valere unici in più tabelle

Companies: 
- UID (unique) 
- NAME 
- other relevant data 

Offices: 
- UID (unique) 
- CompanyID 
- ExternalID 
- other data 

Employees: 
- UID (unique) 
- OfficeID 
- ExternalID 
- other data 

In ognuno di essi l'UID è identificatore unico, creato dal database.

Esistono chiavi esterne per garantire i collegamenti tra Dipendente -> Ufficio -> Società sull'UID.

I campi ExternalID in Uffici e Dipendenti sono l'ID fornito alla mia applicazione dalla Società (i miei clienti in realtà). I clienti non hanno (e non si preoccupano) dei miei ID personali e tutti i dati ricevuti dalla mia applicazione vengono identificati esclusivamente in base ai loro ID (ad esempio ExternalID nelle mie tabelle).

I.e. una richiesta dal client in pseudo-lingua è come "I'm Company X, aggiornare i dati per il mio dipendente Y".

Ho bisogno di forzare l'unicità sulla combinazione di CompanyID e Employees.ExternalID, quindi nel mio database non ci sarà nessun ExternalID duplicato per i dipendenti della stessa azienda.

Stavo pensando a 3 possibili soluzioni:

  1. modificare lo schema per i dipendenti per includere CompanyID e creare vincolo unico su due campi.

  2. Applicare un trigger, che in fase di aggiornamento/inserimento in Dipendenti conferma l'unicità.

  3. Applica il controllo a livello di applicazione (ad esempio il mio servizio di ricezione).

My alternative-dbadmin-in-me sais che (3) è la soluzione peggiore, in quanto non protegge il database di incoerenza in caso di errore dell'applicazione o qualcosa d'altro, e molto probabilmente sarà il più lento uno.

La soluzione di attivazione può essere quello che voglio, ma può diventare complicato, soprattutto se è necessario eseguire più inserimenti/aggiornamenti in una singola istruzione e non sono sicuro della prestazione rispetto a (1).

E (1) sembra l'approccio più rapido e semplice, ma in qualche modo va contro la mia comprensione del modello relazionale.

Quali opinioni degli esperti di SO DB riguardano i pro e i contro di ciascuno degli approcci, specialmente se esiste la possibilità di aggiungere un ulteriore livello di riferimento indiretto - ovvero Azienda -> Ufficio -> Dipartimento -> Dipendente e la stessa unicità deve essere preservato (Azienda/Dipendente).

risposta

3

Hai ragione - # 1 è l'opzione migliore.
Concesso, vorrei metterlo in discussione a prima vista (a causa del taglio corto) ma conoscere la regola aziendale per garantire che un dipendente sia correlato solo a una società - ha senso.

Inoltre, avrei una chiave esterna relativa alla società nel tavolo dei dipendenti alla società nel tavolo dell'ufficio. In caso contrario, consenti a un dipendente di essere correlato a una società senza un ufficio. A meno che sia accettabile ...

I trigger sono l'ultima risorsa se la relazione non può essere dimostrata nel modello di dati e la manutenzione della logica dall'applicazione significa che la logica è centralizzata - non c'è alcuna possibilità che si verifichino cattivi dati, a meno che qualcuno non riduca i vincoli (il che significa che hai problemi più grandi).

+0

@OMG: Sì, le chiavi esterne sono chiavi esterne. Non li ho aggiunti nella Q per semplicità. Grazie comunque per averlo scoperto. Modificherò la Q. –

0

Imposta auto_increment_increment sul numero di tabella che hai. SET auto_increment_increment = 3; (potresti voler impostare questo nel tuo my.CNF)

Quindi impostare manualmente il valore auto_increment partenza di ogni tabella per diversi valori prima tabella 1, seconda tabella 2, terza tabella 3

Tabella 1 avrà valori come 1,4,7, 10,13, ecc

Tabella 2 avrà valori come 2,5,8,11,14, ecc

Tabella 3 avranno valori come 3,6,9,12,15, ecc

Ovviamente questa è solo UNA opzione, personalmente lo farei solo un valore combo e. Potrebbe essere semplice come TableID, AutoincrementID, dove il TableID è costante in tutte le righe.

+0

Questo fallirà spettacolare quando si aggiunge un quarto tavolo. –

+0

Idea interessante. Quindi, in che modo esattamente impone l'unicità della combinazione Company + Employee.ExternalID? –

+1

Nella riflessione la mia idea era stupida, anche se un modo interessante per creare idee uniche è attraverso una tabella dei biglietti. http://code.flickr.com/blog/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/ – MindStalker

1

Ciascuna delle tabelle fornite dalla società deve includere CompanyID nella "chiave UNICA" rispetto agli ID forniti dalla società.

forniti dall'azienda integrità referenziale dovrebbe usare ids forniti dall'azienda:

CREATE TABLE company (
     uid INT NOT NULL PRIMARY KEY, 
     name TEXT 
     ); 

CREATE TABLE office (
     uid INT NOT NULL PRIMARY KEY, 
     companyID INT NOT NULL, 
     externalID INT NOT NULL, 
     UNIQIE KEY (companyID, externalID), 
     FOREIGN KEY (companyID) REFERENCES company (uid) 
     ); 

CREATE TABLE employee (
     uid INT NOT NULL PRIMARY KEY, 
     companyID INT NOT NULL, 
     officeID INT NOT NULL, 
     externalID INT NOT NULL, 
     UNIQIE KEY (companyID, externalID), 
     FOREIGN KEY (companyID) REFERENCES company(uid) 
     FOREIGN KEY (companyID, officeID) REFERENCES office (companyID, externalID) 
     ); 

ecc

+0

Grazie per la risposta, quindi l'opzione uno in movimento. –