table2外部キー制約は、table2のcustomerId値がtable1にcustomerIdとして表示される必要があることを意味します。 table1に表示されないcustomerIDをtable2に挿入しているため、エラーが発生します。
DBMSは自動インクリメントによってtable1customerIDを生成しているため、行を挿入する場合、そのcustomerIDを使用して行をtable2に挿入するには、その値を取得する必要があります。
「table1とtable2の関係はすでに確立している」とは、「外部キー制約を宣言した」という意味だと思います。これは、「table1に挿入した後、DBMSはtable2に挿入するときに、自動生成されたキー値を外部キー値として使用する」という意味だと思います。しかし、それはそれを意味するものではありません。あなたはそれを自分でしなければなりません。外部キー制約は、DBMSがすべてのtable2customerId値がtable1customerId値として表示されることを確認することを意味します。
以前に挿入されたキー値を、そのキーへの外部キーを使用してテーブルに挿入するときに、対応する値として使用でき、使用する必要があります。
DBMSによって生成された自動インクリメントされたキー値を取り戻すには、を使用します。 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');
これがその目的です。ただし、使用しない場合の問題は次のとおりです。
まず、シリアル化されたトランザクションを実行していない場合は、LAST_INSERT_ID()を使用する必要があります。 table1の挿入後、table2の挿入前に、他のユーザーが新しい行を含む行を追加したり、行を削除したり、新しい行を含む行を変更したりする可能性があるためです。したがって、table1を挿入した後、追加したことがわかっているcustomerId値を取得した後、table1のクエリに依存することはできません。
次に、シリアル化されたトランザクションを実行していて、LAST_INSERT_ID()を使用していないとします。
(CustomerName、Address、State)もスーパーキーである場合 table1の、つまりその値は一意です。つまり、SQL UNIQUE / KEY / PKがそのすべてまたは一部の列で宣言されている場合、それを使用して、関連付けられた新しいcustomerIdを照会できます。
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');
ただし、(CustomerName、Address、State)がスーパーキーではない場合 table1の場合、これを行うことはできません。そのサブ行と重複している他の行がtable1にある可能性があるためです。したがって、複数の行を取り戻すことができます。したがって、どれが最新のものかわかりません。代わりに、挿入する前にtable1を照会してから挿入し、customerIdの古いセットと新しいセットの違いを見つける必要があります。
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');
LAST_INSERT_ID()を使用するだけです。
PS:興味深いことに、テーブルの定義を考えると、理想的には次のように書くことができます:
INSERT INTO (
SELECT CustomerName,Address,State,A,B
FROM table1 JOIN table2
USING (CustomerId))
VALUES('value1','value2','value3','valueA','valueB')
結果として生じる可能性のある新しいtable1とtable2の値のペアが1つしかないためです。現在、MySQLの複数のテーブルに関係するものはありませんが、SQLのビューを介したいくつかの法的な更新があります