6

データベースに挿入する文字列のリストがあります。それらは一意でなければなりません。挿入するときは、ID を (別のテーブルの外部キーとして使用するために) 使用したいので、last_insert_rowid を使用します。2つの問題があります。

  1. 置換を使用すると、ID (INTEGER PRIMARY KEY) が更新され、データベースが壊れます (エントリは存在しない ID を指します)
  2. ignore を使用すると、rowid が更新されないため、正しい ID が取得されません

ID を取得するにはどうすればよいですか? 必要がない場合は、選択ステートメントを使用して文字列をチェックし、存在しない場合は挿入したくありません。どうすればいいですか?

4

5 に答える 5

10

UNIQUE 制約違反が発生すると、REPLACE アルゴリズムは、現在の行を挿入または更新する前に、制約違反の原因となっている既存の行を削除し、コマンドは通常どおり実行を続けます。これにより、ROWID が変更され、次の問題が発生します。

Y:> **sqlite3 test**  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> **create table b (c1 integer primary key, c2 text UNIQUE);**  
sqlite> **insert or replace into b values (null,'test-1');**  
sqlite> **select last_insert_rowid();**  
1  
sqlite> **insert or replace into b values (null,'test-2');**  
sqlite> **select last_insert_rowid();**  
2  
sqlite> **insert or replace into b values (null,'test-1');**  
sqlite> **select last_insert_rowid();**  
3  
sqlite> **select * from b;**  
2|test-2  
3|test-1  

回避策は、c2 列の定義を次のように変更することです。

create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);

挿入から「or replace」句を削除します。

挿入後にテストするときは、次のSQLを実行する必要があります。select last_insert_rowid(), changes();

sqlite> **create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);**  
sqlite> **insert into b values (null,'test-1');**  
sqlite> **select last_insert_rowid(), changes();**  
1|1  
sqlite> **insert into b values (null,'test-2');**  
sqlite> **select last_insert_rowid(), changes();**  
2|1  
sqlite> **insert into b values (null,'test-1');**  
sqlite> **select last_insert_rowid(), changes();**  
2|0  

3 回目の挿入後の変更の戻り値は、「test-1」の行 ID が既にファイルにあるため、その行 ID を検索する必要があることをアプリケーションに通知します。もちろん、これがマルチユーザー システムの場合は、これもすべてトランザクションでラップする必要があります。

于 2011-01-27T20:32:57.577 に答える
3

私は現在以下を使用しています

insert into tbl(c_name) select 'val' where not exists(select id from tbl where c_name ='val');
select id from tbl where c_name ='val';
于 2011-01-27T21:50:40.753 に答える
1

「一意である必要があります」とは、一意であると確信していることを意味しますか、そうでない場合は結果としてエラーが発生することを意味しますか?文字列自体をテーブルのキーにするだけでは、1または2のどちらが問題になるのかわかりません。不要な重複がある場合は必要に応じてエラーが発生し、そうでない場合は正しいIDが発生します。使用しているSQLコードの小さな例、問題のテーブル、観察している動作、および代わりに必要な動作を使用して、質問を明確にすることができます...?

編集済み:編集していただきありがとうございますが、SQLがどのような問題を引き起こしているのかはまだわかりません。あなたのテーブルがから来ている場合、例えば:

CREATE TABLE Foo(
  theid INTEGER PRIMARY KEY AUTOINCREMENT,
  aword TEXT UNIQUE ABORT
  )

その場合、重複した単語を挿入しようとすると失敗します(ABORTキーワードはオプションであり、デフォルトであるためUNIQUE)- 「一意である必要があります」という単語を言うと、それはあなたが望むものではありません。つまり、それらがそうじゃない?

于 2009-05-10T08:27:07.653 に答える