De beperking van de externe sleutel van tabel2 betekent dat elke klant-ID van tabel2 moet verschijnen als een klant-ID in tabel1. U krijgt de foutmelding omdat u een klant-ID invoert in tabel2 die niet in tabel1 voorkomt.
Aangezien het DBMS de klant-ID's van tabel1 genereert door automatische verhoging, moet u, als u een rij invoegt, die waarde krijgen om een rij met die klant-ID in tabel2 te kunnen invoegen.
Ik neem aan dat je zegt:"Ik heb al een relatie gelegd tussen tabel1 en tabel2" om te bedoelen dat "ik een externe sleutelbeperking heb aangegeven". En ik denk dat je denkt dat dit betekent "nadat ik het in tabel1 heb ingevoegd, zal het DBMS de automatisch gegenereerde sleutelwaarde gebruiken als de externe sleutelwaarde wanneer ik het in tabel2 invoeg". Maar dat betekent niet. Dat moet je zelf doen. De beperking van de refererende sleutel betekent alleen dat het DBMS controleert of elke table2 customerId-waarde wordt weergegeven als een table1 customerId-waarde.
U kunt en moet elke eerder ingevoegde sleutelwaarde gebruiken als de corresponderende waarde wanneer u deze invoegt in een tabel met een externe sleutel voor die sleutel.
INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(LAST_INSERT_ID(),'valueA','valueB');
Dit is waar het voor is. Maar dit zijn de problemen als je het niet gebruikt.
Ten eerste, als u zich niet in een geserialiseerde transactie bevindt, moet u LAST_INSERT_ID() gebruiken. Omdat na uw table1 insert maar vóór uw table2 insert anderen rijen kunnen hebben toegevoegd en/of verwijderde rijen inclusief uw nieuwe rij en/of gewijzigde rijen inclusief uw nieuwe rij. U kunt er dus niet op vertrouwen dat tabel1 wordt doorzocht nadat de invoeging een klant-ID-waarde heeft gekregen waarvan u weet dat u deze hebt toegevoegd.
Ten tweede, stel dat u zich in een geserialiseerde transactie bevindt en dat u LAST_INSERT_ID() niet gebruikt.
Als (Klantnaam,Adres,State) ook een supersleutel is van tabel1, dat wil zeggen dat de waarden uniek zijn, dat wil zeggen dat SQL UNIQUE/KEY/PK wordt gedeclareerd op alle of enkele van zijn kolommen, dan kunt u het gebruiken om te zoeken naar de bijbehorende nieuwe klant-ID:
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');
Maar als (Klantnaam, Adres, Staat) geen supersleutel is van tabel1 dan kunt u dit niet doen. Omdat andere rijen die duplicaten zijn voor die subrij in tabel1 kunnen staan. Je zou dus meerdere rijen terug kunnen krijgen. Je zou dus niet weten welke de nieuwste is. In plaats daarvan moet u tabel1 opvragen vóór het invoegen, dan invoegen en vervolgens het verschil zoeken tussen de oude en nieuwe reeksen klant-ID's:
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');
Gebruik gewoon LAST_INSERT_ID().
PS:Interessant is dat, gezien de tabeldefinities, idealiter zou kunnen worden geschreven:
INSERT INTO (
SELECT CustomerName,Address,State,A,B
FROM table1 JOIN table2
USING (CustomerId))
VALUES('value1','value2','value3','valueA','valueB')
aangezien er slechts één paar nieuwe table1 &table2 waarden kan ontstaan. Er zijn enkele juridische updates via weergaven in SQL, hoewel er momenteel geen enkele betrekking heeft op meerdere tabellen in MySQL