2012-11-06 2 views
7

SQLite docs、Stack Overflowに関するさまざまな質問と回答、およびthis thingを読んでいましたが、完全な答えが得られていません。SQLiteの挿入または無視元_rowid_

私はSQLiteのでINSERT OR IGNORE INTO foo VALUES(...)ような何かを行うと、元の行のROWIDを取り戻す方法がないこと、およびそれに最も近いINSERT OR REPLACEになることを知っているが、それは、行全体を削除し、新しい行を挿入し、新しいローIDを取得します。

例テーブル:

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 

効率的な)方法は、行をテーブルに挿入して、ROWIDを返すか、私は行を無視するtはすでに存在し、単にROWIDを取得しますか?これは非常に頻繁に起こるため、効率性は重要です。

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

+1

「UPDATE ... WHERE ...」を試しましたか? – Keith

答えて

6

私にとって最良の方法は、insert or ignoreの値であり、2つの別々のステップではrowidです。私は列にuniqueという制約を使用して、選択を高速化し、重複を避けました。

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ステートメントは、私が思ったほど遅くはありません。これはit seemsです。これは、SQLiteによって自動的にunique列のインデックスが作成されるためです。

1

INSERT OR IGNOREは、レコードのIDを気にしない状況のためのものです。その目標は、その特定の値を持つレコードを持つことだけです。

新しいレコードが挿入されているかどうかを知りたい場合は、手動でチェックする必要があります。効率については

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で実行しているのと同じクエリを実行した後に、アクセスパスがキャッシュに格納されるため、パフォーマンスに問題はありません。いずれにしても、INSERT/SELECTクエリを実行するためにはである必要があります(いずれの順序でも、自分と私の両方のコードが動作しますが、より簡単です)。

関連する問題