多対多
0個以上の犬を持つ子と、0個以上の子に属する犬をサポートするには、データベーステーブル構造が多対多の関係をサポートする必要があります。これには3つのテーブルが必要です。
CREATE TABLE child (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
CREATE TABLE dog (
id INTEGER PRIMARY KEY AUTOINCREMENT,
dog TEXT
);
CREATE TABLE child_dog {
child_id INTEGER,
dog_id INTEGER,
FOREIGN KEY(child_id) REFERENCES child(id),
FOREIGN KEY(dog_id) REFERENCES dog(id)
};
挿入方法
3つのテーブルのそれぞれへの挿入は、個別のSQLステートメントである必要がありますが、同じトランザクションのコンテキストで実行できます。child_dogテーブル(マッピングテーブルと呼ばれます)への挿入は、子テーブルと犬テーブルへの挿入後に行う必要があります。これには、2つの関連する理由があります。
- このテーブルに挿入するには、子供と犬の両方の識別子を知っている必要があります。
- 外部キーの制約により、参照されている子や犬がデータベースまたはトランザクションに存在しない場合、child_dogテーブルへの挿入は失敗します。
挿入用のSQLステートメントの例を次に示します。
INSERT INTO child VALUES(NULL, 'bobby');
SELECT last_insert_rowid(); -- gives the id of bobby, assume 2 for this example
INSERT INTO dog VALUES(NULL, 'spot');
SELECT last_insert_rowid(); -- gives the id of spot, assume 4 for this example
INSERT INTO child_dog VALUES(2, 4);
Pythonでの挿入
あなたの質問はPythonについて言及していませんでしたが、この質問にはpythonタグがあるので、Pythonでこれを行う方法を知りたいと思います。Pythonのsqlite3モジュールは、「last_insert_rowid()」関数を明示的に実行する必要をなくす、ちょっとしたショートカットを提供します。
# Import the sqlite3 module
import sqlite3
# Create a connection and cursor to your database
conn = sqlite3.connect('example.db')
c = conn.cursor()
# Insert bobby
c.execute("""INSERT INTO child VALUES(NULL, 'bobby')""")
# The python module puts the last row id inserted into a variable on the cursor
bobby_id = c.lastrowid
# Insert spot
c.execute("""INSERT INTO dog VALUES(NULL, 'spot')""")
spot_id = c.lastrowid
# Insert the mapping
c.execute("""INSERT INTO child_dog VALUES(?, ?)""", (bobby_id, spot_id));
# Commit
conn.commit()
conn.close()