Non esitate a mettere vincoli nel database. Avrai la certezza di avere un database coerente, e questo è uno dei buoni motivi per usare un database. Soprattutto se hai diverse applicazioni che lo richiedono (o solo un'applicazione ma con una modalità diretta e una modalità batch che utilizza fonti diverse).
Con MySQL non hai vincoli avanzati come in postgreSQL, ma almeno i vincoli di chiave esterna sono abbastanza avanzati.
Faremo un esempio, una tabella di società con una tabella di utenti che contiene persone di queste società
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
Diamo un'occhiata alla clausola ON UPDATE :
- IN AGGIORNAMENTO LIMITATO : impostazione predefinita : se si tenta di aggiornare un company_id nella tabella COMPANY, il motore rifiuterà l'operazione se almeno un UTENTE si collega a questa azienda.
- IN AGGIORNAMENTO SENZA AZIONE : uguale a RESTRICT.
- IN AGGIORNAMENTO CASCADE : il migliore di solito : se aggiorni un company_id in una riga della tabella COMPANY, il motore lo aggiornerà di conseguenza su tutte le righe USER che fanno riferimento a questa COMPANY (ma nessun trigger attivato sulla tabella USER, avviso). Il motore seguirà le modifiche per te, va bene.
- IN AGGIORNAMENTO SET NULL : se aggiorni un company_id in una riga della tabella COMPANY, il motore imposterà gli USER company_id correlati su NULL (dovrebbe essere disponibile nel campo USER company_id). Non riesco a vedere nulla di interessante da fare su un aggiornamento, ma potrei sbagliarmi.
E ora sul lato ON DELETE :
- ON DELETE RESTRICT : il valore predefinito : se si tenta di eliminare un ID company_id nella tabella COMPANY, il motore rifiuterà l'operazione se un USER almeno link su questa azienda, può salvarti la vita.
- ON DELETE NO AZIONE : uguale a RESTRICT
- ALLA CANCELLAZIONE DELLA CASCATA : pericoloso : se si elimina una riga dell'azienda nella tabella AZIENDA, il motore eliminerà anche gli UTENTI correlati. Questo è pericoloso ma può essere utilizzato per eseguire pulizie automatiche su tabelle secondarie (quindi può essere qualcosa che desideri, ma sicuramente non per un esempio di UTENTE <-> UTENTE)
- ON DELETE SET NULL : handful : se si elimina una riga COMPANY, gli USER correlati avranno automaticamente la relazione con NULL. Se Null è il tuo valore per gli utenti senza società, questo può essere un buon comportamento, ad esempio forse devi tenere gli utenti nella tua applicazione, come autori di alcuni contenuti, ma rimuovere la società non è un problema per te.
di solito il mio default è: ON ELIMINA RESTRETTO SU AGGIORNAMENTO CASCADE . con alcuni ON DELETE CASCADE
per le tabelle di traccia (registri - non tutti i registri--, cose del genere) e ON DELETE SET NULL
quando la tabella principale è un "attributo semplice" per la tabella contenente la chiave esterna, come una tabella JOB per la tabella USER.
modificare
È passato molto tempo da quando l'ho scritto. Ora penso che dovrei aggiungere un avvertimento importante. MySQL ha una grande limitazione documentata con le cascate. Le cascate non attivano i grilletti . Quindi, se eri abbastanza fiducioso in quel motore da usare i trigger, dovresti evitare i vincoli a cascata.
I trigger MySQL si attivano solo per le modifiche apportate alle tabelle dalle istruzioni SQL. Non si attivano per le modifiche alle viste, né per le modifiche alle tabelle effettuate dalle API che non trasmettono le istruzioni SQL al server MySQL
==> Vedi sotto l'ultima modifica, le cose si stanno muovendo su questo dominio
I trigger non sono attivati da azioni con chiave esterna.
E non credo che questo verrà risolto un giorno. I vincoli di chiave esterna sono gestiti dall'archiviazione InnoDb e i trigger sono gestiti dal motore SQL MySQL. Entrambi sono separati. Innodb è l'unico archivio con gestione dei vincoli, forse un giorno aggiungeranno trigger direttamente nel motore di archiviazione, forse no.
Ma ho la mia opinione su quale elemento dovresti scegliere tra la scarsa implementazione del trigger e l'utilissimo supporto dei vincoli di chiavi esterne. E una volta che ti abituerai alla coerenza del database, amerai PostgreSQL.
12/2017-Aggiornamento di questa modifica su MySQL:
come affermato da @IstiaqueAhmed nei commenti, la situazione è cambiata su questo argomento. Quindi segui il link e controlla la situazione attuale (che potrebbe cambiare di nuovo in futuro).
ON DELETE CASCADE : dangerous
- prendere con un pizzico di sale.