Ograniczenie klucza obcego table2 oznacza, że każda wartość customerId table2 musi pojawić się jako customerId w table1. Otrzymujesz błąd, ponieważ wstawiasz identyfikator klienta do tabeli 2, który nie pojawia się w tabeli 1.
Ponieważ DBMS generuje identyfikatory klientów z tabeli 1 przez automatyczne przyrosty, jeśli wstawisz wiersz, musisz uzyskać tę wartość, aby wstawić wiersz używający tego identyfikatora klienta do tabeli 2.
Myślę, że mówisz „Już ustaliłem relację między tabelą1 i tabelą2”, co ma na myśli „Zadeklarowałem ograniczenie klucza obcego”. I myślę, że myślisz, że to oznacza „po wstawieniu do tabeli 1 DBMS użyje automatycznie wygenerowanej wartości klucza jako wartości klucza obcego, gdy wstawię do tabeli 2”. Ale to nie znaczy. Musisz to zrobić sam. Ograniczenie klucza obcego oznacza po prostu, że DBMS sprawdza, czy każda wartość customerId table2 pojawia się jako wartość clientId table1.
Możesz i musisz użyć dowolnej wcześniej wstawionej wartości klucza jako odpowiedniej wartości podczas wstawiania do tabeli z kluczem obcym do tego klucza.
Aby odzyskać automatycznie inkrementowaną wartość klucza wygenerowaną przez DBMS, użyj 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');
Po to jest. Ale oto problemy, jeśli go nie używasz.
Po pierwsze, jeśli nie jesteś w serializowanej transakcji, musisz użyć LAST_INSERT_ID(). Ponieważ po wstawieniu tabeli 1, ale przed wstawieniem tabeli 2, inni mogli dodać wiersze i/lub usunąć wiersze, w tym nowy wiersz i/lub zmienione wiersze, w tym nowy wiersz. Więc nie możesz polegać na zapytaniu tabeli 1 po jej wstawieniu, aby uzyskać pewną wartość identyfikatora klienta, o której wiesz, że dodałeś.
Po drugie, załóżmy, że jesteś w serializowanej transakcji i nie używasz LAST_INSERT_ID().
Jeśli (CustomerName,Address,State) jest także superkluczem tabeli1, tj. jej wartości są unikalne, tzn. SQL UNIQUE/KEY/PK jest zadeklarowany we wszystkich lub niektórych jej kolumnach, wtedy możesz użyć go do zapytania o powiązany nowy identyfikator klienta:
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');
Ale jeśli (CustomerName,Address,State) nie jest superkluczem tabeli 1 to nie możesz tego zrobić. Ponieważ inne wiersze, które są duplikatami dla tego podrzędu, mogą znajdować się w tabeli1. Więc możesz odzyskać wiele wierszy. Więc nie wiedziałbyś, który jest najnowszy. Zamiast tego musisz wykonać zapytanie table1 przed wstawieniem, następnie wstawić, a następnie znaleźć różnicę między starymi i nowymi zestawami identyfikatorów klientów:
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');
Po prostu użyj LAST_INSERT_ID().
PS:Co ciekawe, biorąc pod uwagę definicje tabel, najlepiej byłoby napisać:
INSERT INTO (
SELECT CustomerName,Address,State,A,B
FROM table1 JOIN table2
USING (CustomerId))
VALUES('value1','value2','value3','valueA','valueB')
ponieważ może powstać tylko jedna para nowych wartości table1 i table2. Istnieją pewne prawne aktualizacje za pośrednictwem widoków w SQL, chociaż obecnie żadna z nich nie obejmuje wielu tabel w MySQL