phpMyAdmin
 sql >> Database >  >> Database Tools >> phpMyAdmin

Come impostare la relazione tra le tabelle In phpMyAdmin

Il vincolo di chiave esterna table2 significa che qualsiasi valore customerId table2 deve apparire come customerId in table1. Ricevi l'errore perché stai inserendo un customerID nella tabella2 che non compare nella tabella1.

Poiché il DBMS sta generando gli ID cliente della tabella1 mediante incremento automatico, se si inserisce una riga è necessario ottenere quel valore per inserire una riga utilizzando tale ID cliente nella tabella2.

Immagino che tu dica "Ho già stabilito una relazione tra table1 e table2" per significare "Ho dichiarato un vincolo di chiave esterna". E immagino che tu pensi che significhi "dopo aver inserito nella tabella1, il DBMS utilizzerà il valore della chiave generato automaticamente come valore della chiave esterna quando inserisco nella tabella2". Ma non significa questo. Devi farlo tu stesso. Il vincolo della chiave esterna significa semplicemente che il DBMS controlla che ogni valore customerId table2 appaia come valore customerId table1.

Puoi e devi utilizzare qualsiasi valore di chiave precedentemente inserito come valore corrispondente quando inserisci in una tabella una chiave esterna a quella chiave.

Per recuperare il valore della chiave a incremento automatico generato dal DBMS, utilizzare LAST_INSERT_ID() :

INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(LAST_INSERT_ID(),'valueA','valueB');

Ecco a cosa serve. Ma ecco i problemi se non lo usi.

Innanzitutto, se non sei in una transazione serializzata, devi utilizzare LAST_INSERT_ID(). Perché dopo l'inserimento della tua tabella1 ma prima dell'inserimento della tua tabella2 altri potrebbero aver aggiunto righe e/o cancellate righe inclusa la tua nuova riga e/o righe modificate inclusa la tua nuova riga. Quindi non puoi fare affidamento sull'interrogazione della tabella1 dopo che il suo inserimento ha ottenuto un valore customerId che sai di aver aggiunto.

In secondo luogo, supponi di essere in una transazione serializzata e di non utilizzare LAST_INSERT_ID().

If (CustomerName,Address,Stato) è anche una superchiave di table1, ovvero i suoi valori sono univoci, ovvero SQL UNIQUE/KEY/PK è dichiarato su tutte o alcune delle sue colonne, quindi puoi usarlo per interrogare il nuovo customerId associato:

set @customerId = (
    SELECT customerId
    FROM table1
    WHERE CustomerName = 'value1'
    AND Address = 'value2'
    AND State = 'value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(@customerId,'valueA','valueB');

Ma se (nome cliente, indirizzo, stato) non è una superchiave di table1, non puoi farlo. Perché altre righe duplicate per quel subrow potrebbero trovarsi in table1. Quindi potresti recuperare più righe. Quindi non sapresti quale è l'ultimo. Invece devi interrogare table1 prima dell'inserimento, quindi inserire, quindi trovare la differenza tra il vecchio e il nuovo set di ID cliente:

CREATE TEMPORARY TABLE table1old (
    customerId (int) PRIMARY KEY
    );
INSERT INTO table1old
SELECT customerId FROM table1;

INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');

set @customerId = (
    SELECT customerId
    FROM table1
    WHERE CustomerName NOT IN table1old);
INSERT INTO table2 (customerId,product,cost)
VALUES(@customerId,'valueA','valueB');

Usa LAST_INSERT_ID().

PS:È interessante notare che, date le definizioni delle tabelle, idealmente si potrebbe scrivere:

INSERT INTO (
    SELECT CustomerName,Address,State,A,B
    FROM table1 JOIN table2
    USING (CustomerId))
VALUES('value1','value2','value3','valueA','valueB')

poiché è possibile ottenere solo una coppia di nuovi valori table1 e table2. Ci sono alcuni aggiornamenti legali attraverso le viste in SQL, sebbene nessuno attualmente coinvolga più tabelle in MySQL