SQL para retornar descontinuidade de ids autoincrement

Bom dia,

Antes de pensar em fazer um algoritmo mais complexo pra isso utilizando vários sqls ou criar uma tabela pra guardar os campos chaves deletados do banco, eu gostaria de saber se é possível fazer com um sql só o seguinte:
Fazer um select para retornar de um determinado intervalo de tuplas todos os campos chaves autoincrement que foram deletados, isto é:
1- JOÃO
2 - MARIA
4 - PEDRO
5 - RAFAEL
7 - FULANO

Nesse caso o SQL retornaria 3, 6. Isso pq desejo utilizar esse indices para os proximos inserts que farei na tabela em alguns casos.

Não existe.
Você sempre terá que retornar um valor que esteja em uma coluna e não um que não esteja.

[quote=drsmachado]Não existe.
Você sempre terá que retornar um valor que esteja em uma coluna e não um que não esteja.[/quote]

Por se tratar de números sequenciais não dá mesmo pra eu fazer tipo um select ao contrário? ahsuashsa… =S

1 - SELECT id FROM tabela WHERE id is null
Vai retornar todos os ids nulos.
2 - SELECT id FROM tabela WHERE id NOT IN (SELECT id FROM tabela WHERE id IS NOT NULL)
Vai retornar todos os ids nulos
3 - SELECT id FROM tabela WHERE id = null
Vai retornar erro

Uma solução é criar uma tabela de log, que receba, através de trigger, as tuplas quando forem deletadas. Ou uma procedure que receba o resultado de

SELECT id FROM tabela

e vá concatenando os valores ausentes.

[quote=drsmachado]1 - SELECT id FROM tabela WHERE id is null
Vai retornar todos os ids nulos.
2 - SELECT id FROM tabela WHERE id NOT IN (SELECT id FROM tabela WHERE id IS NOT NULL)
Vai retornar todos os ids nulos
3 - SELECT id FROM tabela WHERE id = null
Vai retornar erro

Uma solução é criar uma tabela de log, que receba, através de trigger, as tuplas quando forem deletadas. Ou uma procedure que receba o resultado de

SELECT id FROM tabela

e vá concatenando os valores ausentes.[/quote]

É que os ids não são nulos, eles foram deletados, então nem existem! Falei besteira?

Crie uma trigger que seja invocada quando da deleção de algum registro dessa tabela e insira o ID deletado na outra tabela de IDs deletados.

A propósito, isso é mais um capítulo da série “quero reaproveitar um ID”? Sempre que vejo alguma coisa desse tipo fico com medo :roll:

[quote=entanglement]Crie uma trigger que seja invocada quando da deleção de algum registro dessa tabela e insira o ID deletado na outra tabela de IDs deletados.

A propósito, isso é mais um capítulo da série “quero reaproveitar um ID”? Sempre que vejo alguma coisa desse tipo fico com medo :roll: [/quote]

Tenho um sistema de gerenciamento de pizzaria e povo vive errando e deletando registros (lançamento de itens, por exemplo) e os números autoincrement estão ficando muito grandes, por isso queria reaproveitar e pra fazer mais sentido o número com a quantidade de lançamentos existentes (não precisa ser exato, mas pelo menos proximo)

Ah, sei.
Quando é um sistema desses normalmente você apresenta um número de 4 dígitos no máximo para o operador (o autoincrement pode então ter N dígitos que você não vai ter problemas).
O resto dos dígitos o sistema tem de adivinhar. Pode ser, por exemplo, a data do pedido.
Duvido que você consiga ter mais de 10000 pedidos numa pizzaria no mesmo dia (só se for na central de pedidos do Habib’s, mas nesse caso você pode criar um número como 999-999 ou coisa parecida, para simplificar a conferência dos pedidos.
Obviamente se você tem o pedido “0981” você tem de ver se é na verdade o pedido 000981, 010981, 020981 ou sei lá qual.

[quote=entanglement]Ah, sei.
Quando é um sistema desses normalmente você apresenta um número de 4 dígitos no máximo para o operador (o autoincrement pode então ter N dígitos que você não vai ter problemas).
O resto dos dígitos o sistema tem de adivinhar. Pode ser, por exemplo, a data do pedido.
Duvido que você consiga ter mais de 10000 pedidos numa pizzaria no mesmo dia (só se for na central de pedidos do Habib’s, mas nesse caso você pode criar um número como 999-999 ou coisa parecida, para simplificar a conferência dos pedidos.
Obviamente se você tem o pedido “0981” você tem de ver se é na verdade o pedido 000981, 010981, 020981 ou sei lá qual. [/quote]

[quote=discorpio][/quote]

Ta, e como eu faria no meu caso? O banco já está sendo utilizado e tenho muitos dados e lógica em cima de um campo INT que é o ID.
Tem alguma forma de, ao fazer um INSERT(0,…) (já que quando se coloca 0 ele pega e incrementa o último id utilizado automaticamente) ele pegar a data do campo de uma outra tabela, formatar para ficar como inteiro ou long e concatenar com mais esses 4 ou 5 dígitos? Como eu poderia fazer isso na prática?

Tipo:
2012080900001
2012080900002
2012080900003
Daí supondo que a data mudou (aumentou), quero que o increment zere, para ficar assim
2012081000001
2012081000002
2012081000003

Como eu disse, não quero utilizar dois campos pois já fiz muita lógica no sistema em cima de um campo chave só… =S

Hum, agora entendi. Você tem alguma coisa que já está funcionando, certo?

Você reaproveitar códigos que foram deletados não vai ajudar muito.

Digamos que o operador erre 10% dos códigos (ou seja, o operador é realmente muito tosco) e demore 1 mês para que os códigos cheguem a um valor de 5 dígitos, que seja difícil de usar no seu sistema. Se você conseguir reaproveitar todos os códigos deletados, você só vai comprar mais 3 dias (que é 10% de um mês).

O problema seu de ter um autoincrement que em vez de só incrementar, siga uma determinada regra (igual à que eu sugeri), é que isso não existe pronto em bancos de dados* e normalmente você precisa ter uma transação separada no seu sistema só para gerar esse número de sequência (e você obviamente tem de tirar o autoincrement e varrer todas as transações do seu sistema que inserem novas linhas no banco :frowning: )

É sempre alguma coisa chata, porque não é questão de você ter um singleton em memória bem bobinho (como você deve se lembrar, e se o sistema cair? Você teria de descobrir o próximo sequencial de alguma maneira.)

  • OK, você pode criar uma trigger para essa tabela que na inserção crie esse sequencial, não é nada muito impossível de se fazer. A única coisa chata é recuperar o sequencial gerado :frowning: )

Crie um campo chamado “excluido” em suas tabelas e na hora de excluir, em vez de utilizar o DELETE, utilize o UPDATE e seta o campo “excluido” em 1.
E para que não apareça em suas consultas, utilize a condição “excluido” = 0, assim será retornado só os registros que ainda não foram excluído.
E para inserir um novo registro, faça uma busca por registros com o campo “excluido” = 1, se retornar 1 ou mais registros, utilize o UPDATE para armazenar o novo registro, senão faça um INSERT.

Exemplos:

CREATE TABLE perfil (
id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(80) NOT NULL,
excluido TINYINT NOT NULL,
criado DATETIME NOT NULL
);

Verificar se existe algum registro excluído

SELECT id FROM perfil WHERE excluido = 1;

Se o número de registro retornado for igual a 1 ou mais, então você utilizara o UPDATE para cadastrar um novo registro. Mas primeiro obtém um idperfil dos registros retornado pelo SELECT anterior, para utilizar na condição abaixo:

UPDATE perfil SET nome = ‘Maria’, excluido = ‘0’, criado = ‘[Data e Hora Atual]’ WHERE idperfil = 1;

Acrescentamos o campo criado para ordenar pela ordem de inserção em vez pelo id.

Não sei se expliquei bem, mas fica ai a minha ideia!