Pergunta

Eu tenho uma lista de strings para inserir em um db. Eles devem ser exclusivos. Quando eu inserir gostaria seu ID (para usar como uma chave estrangeira em outra tabela) para que eu use last_insert_rowid. Recebo 2 problemas.

  1. Se eu usar substituir, seu id (Integer chave primária) atualizações que Quebra meu ponto db (entradas para IDs inexistentes)
  2. Se eu usar ignorar, rowid não é atualizado, então eu não obter o ID correcto

Como faço para obter suas identificações? se eu não necessidade de i não gostaria de usar uma instrução SELECT para verificar e inserir a cadeia se ele não existe. Como devo fazer isso?

Foi útil?

Solução 2

Eu uso a seguir atualmente

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

Outras dicas

Quando um UNIQUE violação de restrição ocorre, o REPLACE pré-existente algoritmo exclui linhas que estão causando a violação de restrição antes de inserir ou atualizar a linha atual e o comando continua sendo executado normalmente. Isso faz com que o rowid à mudança e cria o seguinte problema

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  

O trabalho em torno é mudar a definição da coluna c2 como segue

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

e remover a "ou substituir" cláusula de suas inserções;

, em seguida, quando o teste após a sua inserção, você precisará executar o seguinte 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  

O valor de retorno de alterações após a terceira inserção será uma notificação para seu aplicativo que você precisará procurar o rowid de "test-1", uma vez que já estava no arquivo. Claro, se este é um sistema multi-usuário, você vai precisar para embrulhar tudo isso em uma transação bem.

Por "eles deve ser único", eles querem dizer que você tem certeza de que eles são, ou que você quer um erro, como resultado, se não forem? Se você acabou de fazer a própria string, uma chave em sua mesa, então eu não entendo como 1 ou 2 poderia ser um problema - você vai obter um erro como desejado em caso de duplicação indesejada, caso contrário, a identificação correta. Talvez você pode esclarecer sua pergunta com um pequeno exemplo de código SQL que você está usando, a tabela em questão, o comportamento que você está observando, e qual o comportamento que você gostaria em vez ...?

Editado: obrigado pela edição, mas ainda não está claro para mim o que SQL está dando o que problemas! Se sua tabela vem, por exemplo:.

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

então qualquer tentativa de inserir uma palavra duplicada falhará (a palavra-chave ABORT é opcional, como é o padrão para UNIQUE) - não é isso que você deseja , uma vez que você diz as palavras " deve ser único", ou seja, é um erro se eles não são?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top