Sqlite insert into with unique names, getting id Sqlite insert into with unique names, getting id sqlite sqlite

Sqlite insert into with unique names, getting id


When a UNIQUE constraint violation occurs, the REPLACE algorithm deletes pre-existing rows that are causing the constraint violation prior to inserting or updating the current row and the command continues executing normally. This causes the rowid to change and creates the following problem

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  

The work around is to change the definition of the c2 column as follows

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

and to remove the "or replace" clause from your inserts;

then when test after your insert, you will need to execute the following 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  

The return value of changes after the 3rd insert will be a notification to your application that you will need to lookup the rowid of "test-1", since it was already on file. Of course if this is a multi-user system, you will need to wrap all this in a transaction as well.


I use the below currently

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';


By "they MUST be unique", do they mean you are sure that they are, or that you want an error as a result if they aren't? If you just make the string itself a key in its table, then I don't understand how either 1 or 2 could be a problem -- you'll get an error as desired in case of unwanted duplication, otherwise the correct ID. Maybe you can clarify your question with a small example of SQL code you're using, the table in question, what behavior you are observing, and what behavior you'd want instead...?

Edited: thanks for the edit but it's still unclear to me what SQL is giving you what problems! If your table comes from, e.g.:

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

then any attempt to INSERT a duplicated word will fail (the ABORT keyword is optional, as it's the default for UNIQUE) -- isn't that what you want given that you say the words "MUST be unique", i.e., it's an error if they aren't?