Pergunta

Eu estou tentando descobrir se existe uma maneira confiável (usando SQLite ) para encontrar o ID da próxima linha a ser inserido, antes que seja inserido . Eu preciso usar o id para outra instrução de inserção, mas não têm a opção de inserir imediatamente e começar a próxima linha.

está prevendo a próxima id tão simples como obter o último id e adicionando um? É que uma garantia?

Editar: Um pouco mais de raciocínio ... Eu não posso inserir imediatamente porque a inserção pode acabar sendo cancelada pelo usuário. Usuário vai fazer algumas mudanças, instruções SQL serão armazenadas, ea partir daí o usuário pode salvar (inserção de todas as linhas de uma vez), ou cancelar (não mudar nada). No caso de uma falha do programa, a funcionalidade desejada é que nada é alterado.

Foi útil?

Solução

De qualquer demolição ou cometer uma série de operações de banco de dados de uma só vez é exatamente o que as transações são para. Consulta BEGIN; antes que o usuário começa a mexer e COMMIT; uma vez que ele / ela fez. Você está garantido que ou todas as alterações são aplicadas (se você cometer) ou tudo é descartado (se você consulta ROLLBACK;, se as falhas do programa, poder sai, etc). Uma vez que você ler a partir do db, você também está garantido que os dados é bom até o final da transação, assim você pode pegar MAX(id) ou o que quiser sem se preocupar com as condições de corrida.

http://www.sqlite.org/lang_transaction.html

Outras dicas

SELECT * FROM SQLITE_SEQUENCE WHERE name='TABLE'; tentativa. Este irá conter um campo chamado seq que é o maior número para a tabela selecionada. Adicione 1 a este valor para obter o próximo ID.

Também ver a SQLite Autoincrement artigo , que é onde as informações acima vieram.

Felicidades!

Você pode provavelmente começar afastado com a adição de 1 ao valor devolvido pela sqlite3_last_insert_rowid sob certas condições , por exemplo, usando a mesma conexão de banco de dados e não há outros escritores concorrentes. Claro, você pode se referir ao código-fonte do SQLite para fazer backup desses pressupostos.

No entanto, você pode também considerar seriamente o uso de uma abordagem diferente que não requer prever o próximo ID. Mesmo se você obtê-lo direito para a versão do SQLite que você está usando, as coisas podem mudar no futuro e que certamente fará com que se mudar para um banco de dados diferente, mais difícil.

Inserir a linha com uma bandeira inválido de algum tipo, obter o ID, editá-lo conforme necessário, eliminar, se necessário ou marca como válido. Isso e não se preocupe com lacunas na seqüência

BTW, você terá que descobrir como fazer a parte inválida a si mesmo. Marcação algo como o trabalho NULL poder dependendo das especificidades.

Editar: Se você puder, sugestão de usar as operações adequadas uso de Eevee. É muito menos trabalho.

Eu percebo seu aplicativo usando SQLite é pequeno e SQLite tem sua própria semântica. Outras soluções postadas aqui pode muito bem ter o efeito que você quer neste cenário específico, mas na minha opinião, cada um deles eu li até agora é fundamentalmente incorreta e deve ser evitado.

Em um ambiente normal segurando uma transação para a entrada do usuário deve ser evitado a todo custo. A maneira de lidar com isso, se você precisa para armazenar dados intermediário, é escrever as informações para uma mesa zero para esse fim e, em seguida, tentar gravar todas as informações em uma transação atômica. Segurando transações convida impasses e pesadelos de simultaneidade em um ambiente multi-usuário.

Na maioria dos ambientes, você pode não assume dados recuperados via Select dentro de uma transação é repetível. Por exemplo

SELECT Balance FROM Bank ...
UPDATE Bank SET Balance = valuefromselect + 1.00 WHERE ...

Após atualizar o valor de equilíbrio pode muito bem ser alterado. Às vezes você pode contornar este problema, atualizando a linha (s) seu interessado em Banco primeira dentro de uma transação como essa é garantido para bloquear a linha prevenir novas atualizações de mudar o seu valor até sua transação foi concluída.

No entanto, por vezes, a melhor maneira de garantir a consistência neste caso é verificar suas suposições sobre o conteúdo dos dados na cláusula WHERE da atualização e verificação de contagem de linhas na aplicação. No exemplo acima, quando você "UPDATE Bank" a cláusula WHERE deve fornecer o valor actual esperado de equilíbrio:

WHERE Balance = valuefromselect

Se o saldo esperado partidas não mais nem a condição WHERE - ATUALIZAÇÃO não faz nada e rowCount retorna 0. Isto diz-lhe que havia um problema de concorrência e você precisa executar novamente a operação novamente quando algo não está tentando mudar seus dados ao mesmo tempo.

select max(id) from particular_table is unreliable for the reason below..

http://www.sqlite.org/autoinc.html

"O algoritmo de seleção ROWID normais descrito acima irá gerar monótona crescente ROWIDs únicas, desde que você nunca use o valor máximo ROWID e você nunca excluir a entrada na tabela com o maior ROWID. Se você nunca linhas apagar ou se você já criar uma linha com o ROWID máximo possível, então ROWIDs de linhas excluídos anteriormente pode ser reutilizado na criação de novas linhas e ROWIDs recém-criado pode não estar em ordem ascendente estritamente. "

Eu acho que isso não pode ser feito porque não há maneira de ter certeza de que nada será inserido entre você perguntar e você inserir. (Você pode ser capaz de bloquear a tabela para inserções mas Yuck)

Por sinal, eu só usei o MySQL, mas eu não acho que vai fazer qualquer diferença)

O mais provável é que você deve ser capaz de +1 a id mais recente. Eu olhava para todos (voltando um pouco) do existente ID do na tabela ordenada .. São consistentes e é ID de cada linha é um a mais que o último? Se assim for, você provavelmente vai ficar bem. Eu deixaria de comentários no código explicando a suposição no entanto. Fazendo um bloqueio vai ajudar a garantir que você não está recebendo linhas adicionais enquanto você faz isso bem.

Selecione o valor last_insert_rowid ().

A maioria de tudo o que precisa ser dito neste tópico já ... No entanto, ter muito cuidado com as condições de corrida ao fazer isto. Se duas pessoas tanto abrir a sua aplicação / web / whatever, e um deles adiciona uma linha, o outro usuário tentar inserir uma linha com o mesmo ID e você terá muitos problemas.

select max(id) from particular_table;

O próximo id será +1 do id máxima.

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