22

私はSQLiteのドキュメント、スタックオーバーフローに関するさまざまな質問と回答、およびこのことを読むのに時間を費やしましたが、完全な回答には至っていません。

INSERT OR IGNORE INTO foo VALUES(...)SQLite のようなことをして元の行の rowid を取得する方法はなく、最も近いINSERT OR REPLACE のは行全体を削除して新しい行を挿入し、新しい rowid を取得する方法がないことを私は知っています。

表の例:

CREATE TABLE foo(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    data TEXT
);

今、私はできる:

sql = sqlite3.connect(":memory:")
# create database
sql.execute("INSERT OR IGNORE INTO foo(data) VALUES(?);", ("Some text.", ))
the_id_of_the_row = None
for row in sql.execute("SELECT id FROM foo WHERE data = ?", ("Some text.", )):
    the_id_of_the_row = row[0]

しかし、理想的なものは次のようになります。

the_id_of_the_row = sql.execute("INSERT OR IGNORE foo(data) VALUES(?)", ("Some text", )).lastrowid

行をテーブルに挿入して行IDを返す、または行が既に存在する場合は無視して行IDを取得するための最良の(読み取り:最も効率的な)方法は何ですか? これは非常に頻繁に発生するため、効率が重要です。

INSERT OR IGNORE無視された行が比較された行の行 ID を返す方法はありますか? 挿入と同じくらい効率的であるため、これは素晴らしいことです。

4

2 に答える 2

17

私にとって最もうまくいった方法はinsert or ignore、値とselect2つの別々のステップでのROWIDでした。unique列に制約を使用して、data選択を高速化し、重複を回避しました。

sql.execute("INSERT OR IGNORE INTO foo(data) VALUES(?);" ("Some text.", ))
last_row_id = sql.execute("SELECT id FROM foo WHERE data = ?;" ("Some text. ", ))

ステートメントは、select私が思っていたほど遅くはありません。これは、 SQLite が列のインデックスを自動的に作成するためのようです。unique

于 2012-11-14T20:19:53.553 に答える
0

INSERT OR IGNOREレコードのアイデンティティを気にしない状況向けです。目標は、その特定の値を持つレコードを持つことだけです

新しいレコードが挿入されたかどうかを知りたい場合は、手動で確認する必要があります。

the_id_of_the_row = None
for row in sql.execute("SELECT id FROM foo WHERE data = ?", ...):
    the_id_of_the_row = row[0]
if the_id_of_the_row is None:
    c = sql.cursor()
    c.execute("INSERT INTO foo(data) VALUES(?)", ...)
    the_id_of_the_row = c.lastrowid

効率性について: SQLite がdata列の重複をチェックするときSELECTは、.問題。いずれにせよ、 2 つの個別の/クエリを実行する必要あります (どちらの順序でも、あなたのコードと私のコードの両方が機能しますが、あなたのコードの方が簡単です)。INSERTSELECT

于 2012-11-06T08:14:58.727 に答える