Вставка Sqlite с уникальными именами, получение идентификатора

StackOverflow https://stackoverflow.com/questions/844885

Вопрос

У меня есть список строк для вставки в базу данных.Они ДОЛЖНЫ быть уникальными.Когда я вставляю, мне нужен их идентификатор (использовать в качестве внешнего ключа в другой таблице), поэтому я использую Last_insert_rowid.У меня 2 проблемы.

  1. Если я использую заменить, их идентификатор (целочисленный первичный ключ) обновления, которые разбивают мой DB (записи указывают на несуществующие идентификаторы)
  2. Если я использую игнорировать, rowid не обновляется, поэтому я не получаю правильный идентификатор.

Как мне получить их идентификаторы?если бы мне это не нужно, я бы не хотел использовать оператор выбора для проверки и вставки строки, если она не существует.Как мне это сделать?

Это было полезно?

Решение 2

В настоящее время я использую приведенное ниже

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

Другие советы

Когда происходит нарушение ограничения UNIQUE, алгоритм REPLACE удаляет ранее существовавшие строки, вызывающие нарушение ограничения, перед вставкой или обновлением текущей строки, и команда продолжает выполняться в обычном режиме.Это приводит к изменению идентификатора строки и создает следующую проблему.

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

и удалить предложение «или заменить» из ваших вставок;

тогда при тестировании после вставки вам нужно будет выполнить следующий 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  

Возвращаемое значение изменений после третьей вставки будет уведомлением вашего приложения о том, что вам нужно будет найти идентификатор строки «test-1», поскольку он уже был в файле.Конечно, если это многопользовательская система, вам также нужно будет обернуть все это в транзакцию.

Под «они ДОЛЖНЫ быть уникальными» означают ли они, что вы уверены, что они уникальны, или что вы хотите, чтобы в результате возникла ошибка, если это не так?Если вы просто сделаете саму строку ключом в своей таблице, то я не понимаю, как 1 или 2 могут быть проблемой - вы получите желаемую ошибку в случае нежелательного дублирования, в противном случае правильный идентификатор.Может быть, вы можете прояснить свой вопрос с помощью небольшого примера используемого вами кода SQL, рассматриваемой таблицы, какое поведение вы наблюдаете и какое поведение вы бы хотели вместо этого...?

Отредактировано:спасибо за редактирование, но мне до сих пор неясно, какой SQL доставляет вам какие проблемы!Если ваша таблица взята, например:

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

то любая попытка ВСТАВИТЬ дублированное слово завершится неудачей ( ABORT ключевое слово является необязательным, так как оно используется по умолчанию для UNIQUE) -- разве это не то, что ты хотеть учитывая, что вы говорите слова «ДОЛЖНЫ быть уникальными», т. е. если это не так, это ошибка?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top