2012-01-21 18 views
0

外部変数として自動インクリメントSQL変数を使用したいと思います。コードはPython/SQLで書かれています(これを言う正しい方法は何ですか?) しかし、実際の数値を入れない限り、私は外部キー制約エラーを受け取ります。AutoIncrement変数を外部キーとして使用 - 外部キーを取得するcontraintエラー

私はこれらのエラーに関する複数の記事を読み、情報を使用しようとしている...ここで

は私の二つのテーブルです。表1は上部、表2は下部です。 IDは外部キーです。 私はエラーを防ぐためにコードに1を入れました。

+----+------+-------+ 
| id | name | class | 
+----+------+-------+ 
| 1 | ONE | TWO | 
| 2 | ONE | TWO | 
| 3 | ONE | TWO | 
| 4 | ONE | TWO | 
+----+------+-------+ 

mysql> select * from table2; 

+-----+------+-------+----+ 
| par | name | class | ID | 
+-----+------+-------+----+ 
| 1 | SSS | CAR | 1 | 
| 2 | SSS | CAR | 1 | 
+-----+------+-------+----+ 

そして、ここでFOREIGN KEY(ID)とREFERENCESの間にカンマ(表2)を入れてthing-コード

sql= """CREATE TABLE IF NOT EXISTS table1 (
     `ID` integer NOT NULL AUTO_INCREMENT, 
    `name` varchar(30) default NULL, 
    `class` varchar(20) default NULL, 
     PRIMARY KEY (`ID`) 
     )""" 
cursor.execute(sql) 

sql2 = """CREATE TABLE IF NOT EXISTS table2 (
    `par` integer NOT NULL AUTO_INCREMENT, 
    `name` varchar(30) default NULL, 
    `class` varchar(20) default NULL, 
    `ID` integer NOT NULL, 
    FOREIGN KEY (ID) REFERENCES table1 (ID), 
    PRIMARY KEY (par) 
)"""   
cursor.execute(sql2)   

query = "INSERT INTO table1 (name, class) VALUES('ONE','TWO')" 
cursor.execute(query) 

query2 = "INSERT INTO table2 (name, class,ID) VALUES('SSS','CAR',1)" 
cursor.execute(query2) 

つ以上あるエラーが発生します。 ??

編集:私の質問ははっきりしないと思います。私が欲しいのは表1にtable2の

`ID` integer NOT NULL, 
     FOREIGN KEY (ID) 

参照

`ID` integer NOT NULL AUTO_INCREMENT,  
    PRIMARY KEY (`ID`) 

編集に 'ID' を作ることです。 LAST_INSERT_ID()単一の行を挿入するために動作します。 MySQL documentationには、複数行の使用方法が記載されています。 テーブル2には複数の行があります。 UPDATEテーブル2 SET ID = LAST_INSERT_ID(ID + 1);

私はこの方法を使用してエラーメッセージがある: は、子行を追加または更新できません:外部キー制約が失敗した(。dbtable2、CONSTRAINT table2_ibfk_1 FOREIGN KEY(IDtable1ID)を参照)

+0

@ダニエルどのようにしましたか? – Tom

+0

あなたの質問は何ですか?どこでエラーが発生していますか? –

+0

行のquery2 = ...、そこに「1」を入れないとエラーが出ます。私はtable1のautoincrementsのIDを参照したいと思います。だから私は外国キーの仕事をするために1の代わりに何を置くべきかを知りたがっている – Tom

答えて

1

クエリ2では、1がある場合は、table1にIDの値のいずれかを挿入する必要があります。これはFKの意味であり、参照先のテーブルに値を挿入しないとエラーを投げることになります。

+0

はい、それは私がそこに1を置く理由です。しかし、どのように参照する変数のように、1の自動インクリメントを行うのですか? – Tom

+0

もう1つの応答として、LAST_INSERT_IDを使用できます。しかし、あなたはそれをオートインクリメントにするべきではありません。 1対1を常に挿入している場合は、同じエンティティで同じテーブルに存在する必要があります。もしあなたが挿入したものを制御するべきでないなら、あなたはテーブルの一つにレコードを挿入し、他のテーブルにはレコードを挿入したくないかもしれません。 – Luis

0

質問1)MySQLはLAST_INERT_ID()を提供しています。単一行操作の場合、最後に生成された自動インクリメント番号が返されます。複数行の挿入の場合、LAST_INSERT_ID()は操作のために生成された最初の番号を戻すので、挿入された行の数を追跡する必要があります。ここで

は、1対1の例である:ここでは

query = "INSERT INTO table1 (name, class) VALUES('ONE','TWO')" 
cursor.execute(query) 

query2 = "INSERT INTO table2 (name, class,ID) VALUES('SSS','CAR',LAST_INSERT_ID())" 
cursor.execute(query2) 

は1対多の例です:

#Insert the parent record 
query = "INSERT INTO table1 (name, class) VALUES('ONE','TWO')" 
cursor.execute(query) 

#get the autoincrement id 
cursor.execute('select LAST_INSERT_ID()') 
parentId = cursor.fetchone()[0] 

#Assuming you have several child records as a list of lists 
childVals = [['SSS','CAR'],['FOO','BAR']] 

#define the template child insert SQL using parameter substitution 
# many dbapi modules use ? as the parameter placeholder, yours may use %s, etc. 
query2 = "INSERT INTO table2 (name, class,ID) VALUES(?,?,?)" 

#insert the child records with the parent id 
for vals in childVals: 
    #pass in the child record values with the parent id 
    cursor.execute(query2, vals + [id]) 

質問2)参照するにはどこを探しへの外部キーを語っていますしたがって、それらは同じステートメントの一部であり、コンマで区切ってはいけません。

+0

複数行の挿入を行う方法がわかりません。私は外部キー制約エラーを受け取ります – Tom

+0

複数の子レコードを挿入するための1対多の例を追加しました。複数の親レコードを追加する場合は、最初に親挿入ステートメントを繰り返し実行することをお勧めします。最も効率的ではありませんが、それはまっすぐです。 – tharen

+0

insert文が複数の行を一度に生成している場合、**カーソルは通常、影響を受ける行の数、 'cursor.rowcount'を報告します。この行数を使用してLAST_INSERT_ID()応答を増やします。 – tharen