You are on page 1of 3

Identity en SQL Server

Archivado en: Identitys, SQL Server — Etiquetas: Base de datos, SQL Server — grimpi @ 11:25 pm
Quienes trabajaron mínimamente en alguna versión de SQL Server, conocerán los campos Identitys, que son columnas cuyo valor es autoincremental. Hay muchas discusiones sobre las ventajas y desventajas del uso de este tipo de campos, para las columnas que componen la clave primaria (PK), pero es algo que ya voy a tratar en otro artículo. Por el momento muestro un listado de tips que cualquier programador que trabaje con SQL Server debería saber al respecto de los campos Identitys: 1) Resetear el valor del campo identity: Mucha gente piensa que no es posible resetear el contador de un identity de una tabla. FALSO. Existen dos formas de hacerlo, una es mediante TRUNCATE TABLE. Cuando hacemos un TRUNCATE de una tabla, además de borrar todo su contenido, reseteamos el valor del campo Identity. Esto es muy obvio, porque un TRUNCATE TABLE no hace nada más y nada menos que borrar la tabla y volver a crearla. La segunda opción (y la que nos interesa) es usar el comando DBCC CHECKIDENT. Esta instrucción permite setera el valor que queremos del campo Identity. Su sintaxis es la siguiente:

DBCC CHECKIDENT <NombreDeTabla>,RESEED,NuevoValor
Hay que tener mucho cuidado con el uso de este comando, ya que podemos setear un valor menor al máximo de la tabla actual y crear en algún momento un valor duplicado. Una opción interesante de este comando es asignar al campo el valor máximo de la tabla + 1, y así garantizar que no tendremos problemas de registros duplicados, para eso solo hay que poner:

DBCC CHECKIDENT <NombreDeTabla>
2) Insertar valores explícitos en un campo Identity: Cuando se inserta un registro en una tabla con un campo Identity, este se incrementa automáticamente y si queremos modificar o insertar este valor manualmente, el SQL nos tira error y nos indica que no es posible. Sin embargo, algunas veces puede que necesitemos deshabilitar temporalmente la propiedad Identity, y poder ingresar un valor explícito a la tabla. Generalmente queremos hacer algo así cuando hacemos copias o replicaciones de una tabla de una base a otra tabla. Para esto, tenemos la opción:

SET IDENTITY_INSERT <NombreDeTabla> ON
Con esta opción, podemos insertar valores en un campo Identity como si fuese un campo más. Luego, cuando terminamos de insertar valores, hay que volver habilitar nuevamente la propiedad Identity del campo. Para eso, corremos el mismo comando anterior, pero con el parámetro OFF.

SET IDENTITY_INSERT <NombreDeTabla> OFF
3) Capturar el valor en un INSERT: Muchas veces cuando tenemos una tabla con un campo Identity, al hacer un INSERT, queremos saber cuál es el valor que insertó en este campo. Lo mas común en estos casos es usar @@Identity, que es una variable global que indica el valor del último campo identity insertado en cualquier tabla de la base. Esto último es un detalle muy importante. Si la tabla contiene un trigger que inserta registros en otra tabla, o antes de leer la variable @@Identity, se inserta otro registro en cualquier tabla de la base, el valor @@Identity, tendrá un valor diferente al que estábamos esperando. Para resolver esta situación, tenemos dos funciones muy útiles: SCOPE_IDENTITY e IDENT_CURRENT. La función SCOPE_IDENTIY nos devuelve el último valor generado dentro de un scope, o sea dentro de un entorno, ya sea un Store Procedure, Function o Trigger. En nuestro caso anterior, como el trigger esta fuera del scope, la función SCOPE_IDENTIY nos devolvería el valor que queremos. Pero por otro lado, tenemos la función, IDENT_CURRENT, donde se le pasa por parámetro el nombre de la tabla y nos devuelve el ultimo valor identity generado para esta tabla, sin importar el scope. Esta opción en mi opinión es la más clara. Su sintaxis es la siguiente:

SELECT IDENT_CURRENT(‘NombreTabla’)
4) Capturar los valores Identity en un INSERT con multiples registros:

el ejemplo anterior no nos sirve. is_not_for_replication. Nombre VARCHAR(50)) INSERT SELECT UNION SELECT UNION SELECT INTO Cliente ‘Esteban’ ‘Juan’ ‘Ricardo’ SELECT IDENT_CURRENT(‘Cliente’) Como ya dijimos antes. IDENT_CURRENT solo nos va a devolver el valor del identity del registro ‘Ricardo’.ClienteID INTO @NuevosIdentitys(ID) SELECT ‘Esteban’ UNION SELECT ‘Juan’ UNION SELECT ‘Ricardo’ SELECT * FROM @NuevosIdentitys 5) Detectar si una columna es Identity: Usando la función COLUMNPROPERTY. increment_value. que permite capturar el valor de las operaciones INSERT y DELETE. existe la interesante clausula OUTPUT. seed_value.identity_columns 6) Obtener el valor de la columna Identity aun si saber el nombre del campo: . si se aplica o no también para casos de replicación (IsNotForReplication). SELECT COLUMNPROPERTY(OBJECT_ID(‘<NombreDeTabla>’). como por ejemplo el valor inicial. que usa OUTPUT y almacena los valores de los registros insertados en una variable de tabla. consiste en usar la vista sys. etc. DECLARE @NuevosIdentitys TABLE (ID INT) INSERT INTO Cliente OUTPUT INSERTED. Veamos entonces este ejemplo. ya que estas solo devuelven el ultimo valor insertado. por lo tanto. Ni la funcion IDENT_CURRENT ni SCOPE_IDENTITY nos sirven. más potente. que además de determinar si una columna es Identity. is_identity. SELECT Name. podemos obtener esta información.identity_columns (solo a partir de SQL Server 2005).Supongamos que insertamos en una sola sentencia INSERT.‘IsIdent ity’) Otra opción. mas de un registro en una tabla. last_value FROM sys. que fue el último registro que se insertó.’<NombreColumna>‘. Pero a partir de SQL Server 2005. Como hacemos para capturar el valor de la columna identity de todos los nuevos registros insertados?. Veamos este ejemplo: CREATE TABLE Cliente (ClienteID INT IDENTITY. nos permite obtener mayor información sobre la columna relacionada con esta propiedad. pero a nosotros nos interesan todos los valores insertados. el valor de incremento.

Supongamos que queremos obtener el valor de una columna que sabemos que es identity. pero solo sabemos el nombre de la tabla (en situaciones donde ejecutamos SQL dinámico podría llegar a darse un caso así). Existe en SQL Server una función que se llama IDENTITYCOL. SELECT IDENTITYCOL FROM <NombreDeTabla> . que precisamente nos devuelve este valor que queremos averiguar.