Вставка Sqlite с уникальными именами, получение идентификатора
-
20-08-2019 - |
Вопрос
У меня есть список строк для вставки в базу данных.Они ДОЛЖНЫ быть уникальными.Когда я вставляю, мне нужен их идентификатор (использовать в качестве внешнего ключа в другой таблице), поэтому я использую Last_insert_rowid.У меня 2 проблемы.
- Если я использую заменить, их идентификатор (целочисленный первичный ключ) обновления, которые разбивают мой DB (записи указывают на несуществующие идентификаторы)
- Если я использую игнорировать, 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
) -- разве это не то, что ты хотеть учитывая, что вы говорите слова «ДОЛЖНЫ быть уникальными», т. е. если это не так, это ошибка?