PDA

Ver la Versión Completa : Identity en SQL


paladincubano
19-05-2008, 17:58:16
Hola amigos del club.
Tengo muchas tablas, muchas de ellas para el indice hago un campo automatico de tipo Longint y le digo que sea el Primary Key y que sea Indentity con incremento de 1 en 1.
Por supuesto todo funciona a la perfecccion.
Me he dado cuenta que al crear registros por supuesto ese campo se incrementa de 1 en 1. Cuando borro registros, en vez de ocupar esos valores borrados, sigue en su consecutivo...
Pero tengo unas dudas ya que soy una persona que me gusta precaver todas las cosas en mis aplicaciones.

- Se que llenar un longint de 1 en 1 es bastante dificil, pero...si ese valor lleguara al maximo de un Longint, que pasaria en mi tabla? Empezaría de 1 de nuevo llenando los que no esten ocupados o daria error??
- Hay alguna forma de ordenarle al SQL que empiece ese valor nuevamente de 1??
Me preocupa porque uso ese campo a la hora de ordenar registros y si esas cosas pasan se puede liar un poco mi aplicacion.
Gracias por la atencion.

BlueSteel
19-05-2008, 18:17:27
Hola

Con que motor de base de datos estas trabajando ???

Salu2:p:D

paladincubano
19-05-2008, 18:20:04
Perdona por olvidar poner el motor (imperdonable)
De momento uso el SQLExpress 2005. Pero con perspectivas de SqlServer 2005.
Gracias por el interes.

BlueSteel
19-05-2008, 18:30:00
indice hago un campo automatico de tipo Longint y le digo que sea el Primary Key y que sea Indentity con incremento de 1 en 1.

Estas seguro que de tipo Longint... es que estoy revisando la documentación del SQL Server 2005 y no me aparece ese tipo de dato...y revise en el Server 2000 y tampoco lo tengo

Salu2:p:D

paladincubano
19-05-2008, 18:40:47
Jajajaa, estas para fastidiarme, de nuevo perdonnnnnnnnnnnn, lo he confundido con el tipo en delphi. En SQL es el BigInt. OK???????????
Algo mas????
saludos.

BlueSteel
19-05-2008, 18:50:51
Veamos el uso de DBCC CHECKIDENT en SQL Server:

use AdventureWorks
DBCC CHECKIDENT ('Production.Product')
Al ejecutar esta instrucción devuelve un resultado informando lo siguiente:

Checking identity information: current identity value '999', current column value '999'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Ahora veamos la funcionalidad de regeneración del DBCC CHECKIDENT:

use AdventureWorks
-- Verifica los valores de la columna Identity
-- de la tabla
DBCC CHECKIDENT ('Production.Product', NORESEED)

-- Asigna el próximo valor de Identity si el valor]
-- del último registro es menor al siguiente valor
-- de la semilla.
DBCC CHECKIDENT ('Production.Product', RESEED)

-- Asigna el valor que de la semilla al valor
-- que se desea. En este ejemplo, se reinicia el valor
-- de la columna a 1.
DBCC CHECKIDENT ('Production.Product', RESEED, 1)



Revisa la publicación completa en el sgte hilo (http://msmvps.com/blogs/otelis/archive/2007/06/19/utilidades-de-sql-server-con-ado-net-regenerar-campos-identity.aspx).. gentileza de san google (http://www.google.cl/search?hl=es&sa=X&oi=spell&resnum=0&ct=result&cd=1&q=resetear+valor+tipo+identidad+sql+server&spell=1)

Salu2:p:D

BlueSteel
19-05-2008, 18:54:25
Jajajaa, estas para fastidiarme, de nuevo perdonnnnnnnnnnnn, lo he confundido con el tipo en delphi. En SQL es el BigInt. OK???????????
Algo mas????
saludos.


Hola.. en todo caso... crees que podras llenar todos los registros en el tipo BigInt...has visto hasta cuanto soporta....


Tipo de datos Intervalo Almacenamiento
bigint De -2^63 (-9.223.372.036.854.775.808) a 2^63-1 (9.223.372.036.854.775.807) 8 bytes


Salu2:p:D

paladincubano
19-05-2008, 19:29:02
Vale tu ganas man.
Ahora una ultima cosa. Si me gustaria poder reoordenarlos, o sea, tengo

1
2
6
10
11
14
15
19

Hay alguna forma de reoordenarlos para que cojan bien los consecutivos. Osea, algun comando?
Ya es lo ultimo te lo prometo.
gracias por todo.

BlueSteel
19-05-2008, 19:39:34
Vale tu ganas man.
Ahora una ultima cosa. Si me gustaria poder reoordenarlos, o sea, tengo

1
2
6
10
11
14
15
19

Hay alguna forma de reoordenarlos para que cojan bien los consecutivos. Osea, algun comando?
Ya es lo ultimo te lo prometo.
gracias por todo.

En realidad no se si exista algun comando.... creo que deberias buscar el no consecutivo lo hayas.. y se lo reasignas....

o simplemente trabajar con otra tabla...trapasar todos los datos a otra tabla, resetear el campo identidad.. y volver a traspasarlos, así se conservarán la continuidad y sin saltos.. bueno.. esto hasta que se te ocurran borrar nuevamente otros registros...

Salu2:p:D

paladincubano
19-05-2008, 19:54:03
Ya habia pensado en esa solucion que das, a la verdad creo que es la unica que veo logica. Porque estuve leyendo el blog que me pusistes y lo que hacen es eso mismo, rellenar con el valor que este disponible en ese momento.
Microsoft deberia pensar en un comandito para reorganizar el campo identity, seria muy util y organizada la tabla.
De momento seguire buscando, si encuentro una solucion la posteare.
Gracias por todo.

xjre
20-05-2008, 20:38:04
Hola ¿Que tal?

Mira, yo te voy a dar la perspectiva desde la que trabajo yo. No utilizo IDENTITY salvo cuando quiero armar una lista en una tabla temporal y ponerle el numeraje a las lineas. La razón por la cual hago es es, simple y llanamenta , porque asi me acostumbraron (supuestamente "no recomiendan en ningun lado usar identity" porque no se que razón bla bla, nunca lo vi en google, para mi es un mito)

Ahora bien, ¿Cómo indexo entonces?

Suponete que tenemos la tabla HeaderPedido con un campo llamado NumeroPedido y otro no se, NombrePedido

Entonces:




Código SQL [-] (http://www.clubdelphi.com/foros/#)
Begin tran

declare @NumeroPedido int

set @NumeroPedido = IsNull((select Max(NumeroPedido) from HeaderPedido),0) + 1

Insert HeaderPedido(NumeroPedido, NombrePedido)
Values(@NumeroPedido, 'Bla')

If @@error <> 0
goto Error


Commit Tran
select @NumeroPedido as NumeroPedido



Error:
Rollback
select 0 as NumeroPedido





Ahora, en mi caso al menos yo no borraría nunca un pedido sino perdería el historial de pedidos (incluso los que se borraron). De hecho, si tenes un Primary Key en una tabla, es porque casi seguro la estas relacionando con otra. Suponete que tenga otra tabla que sea "ItemPedido" cuyas columnas sean: NumeroPedido, NumeroItem, NombreItem. Si vos renumeras la columna NumeroPedido de la tabla HeaderPedido, vas a perder la conexión. Mas aún, si vos tenes una relación física en la base de datos, ni siquiera te va a dejar borrarla.

Respondiendo a lo que vos apuntas y aplicandolo al ejemplo que estoy siguiendo, yo creo que lo que deberías que la tabla HeaderPedido sea:


Código SQL [-] (http://www.clubdelphi.com/foros/#)
create table HeaderPedido
(
Id_HeaderPedido int IDENTITY(1,1),
NumeroPedido int,
NombrePedido varchar(50)
)





Entonces la Id la utilizas para las relaciones, y luego el NumeroPedido (en el caso de que en tu lógica de negocio se pueda hacer) le asignas correlativo o alguna que falte en el medio.

Ponele que haces un procedimiento para eso:


Código SQL [-] (http://www.clubdelphi.com/foros/#)
create proc NumeroPedidoLibre
(
@NumeroPedido int output
)
as
BEGIN

// Declaro variables a usar
declare @Auxiliar int, @Contador int

//Inicializo Contador
set @Contador = 1
set @NumeroPedido = 0

// Declaro un cursor que recorra la tabla HeaderPedido

declare pedidos cursor for select NumeroPedido from HeaderPedido
open pedidos

fetch next from pedidos into @Auxiliar

while @@fetch_status = 0 and @NumeroPedido = 0
BEGIN

//Como la variable Contador va sumando de a uno
// se supone que si en algun momento la variable
// auxiliar no es igual al contador es porque el
// numero pedido igual al contador no existe

if(@Auxiliar <> @Contador)
Begin
set @NumeroPedido = @Contador
End

set @Contador = @Contador + 1

fetch next from pedidos into @Auxiliar

END
close pedidos
deallocate pedidos

// Si @NumeroPedido es igual a cero, significa que
// existen todos los numeros pedidos y son correlativos

if(@NumeroPedido = 0)
Begin
set @NumeroPedido = @Contador + 1
End

END





Entonces en vez de usar el select max de arriba, usas:


Código SQL [-] (http://www.clubdelphi.com/foros/#)

declare @NumeroPedido

exec NumeroPedidoLibre @NumeroPedido output






Y listo, eso debería andar

Cualquier cosa chifla


Saludos