2009-02-18 7 views
7

¿Existe una consulta de tsql para indicar qué valor de la columna de identidad del servidor SQL espera utilizar para la siguiente inserción de fila?¿Cómo se puede saber qué será la próxima columna de identidad?

Editado para añadir:

He eliminado y recreado una mesa con

[personID] [int] IDENTITY(1,1) NOT NULL 

como parte de mi comando CREATE TABLE. También intenté resembrar columnas de identidad al eliminar toda la información en esa tabla y eso no siempre ha funcionado. Me hizo preguntarme si había una forma de ver qué SQL esperaba usar para su próximo número de columna de identidad.

+0

No es que yo sepa, pero ¿por qué quieres saber? ¿Cuál es el problema general? – colithium

+0

Si desea un lavado rápido de la tabla, 'truncar tabla' vuelve a guardar automáticamente todas las columnas de identidad – SWeko

Respuesta

10

No, no hay ninguna garantía de manera (aunque ciertamente puede averiguar cuál es el siguiente valor podría ser, otro comando podría ir y utilizarlo antes de que pueda hacer uso de ella). El único valor garantizado que puede recuperar es previamente valor de identidad insertado a través de SCOPE_IDENTITY() (que devolverá el valor de identidad último generado para el alcance actual).

Es cuestionable el propósito por el cual uno necesitaría saber el valor antes (cuando se usa una columna de identidad automáticamente aumentada).

Si necesita conocer el valor antes, entonces le recomiendo que genere los identificadores. Puede hacer esto con una tabla de ids codificada en el nombre de la tabla o, si tiene inquietudes de escalabilidad (y está utilizando transacciones), puede tener una tabla de id para cada tabla que necesite un id que tenga el ID insertado (y posteriormente incrementado).

O bien, podría usar un GUID, y podría generarlos fácilmente en el lado del cliente antes de enviarlo a su base de datos.

+0

cool, FYI: http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity -vs-ident_current-retrieve-last-inserted-identity-of-record/ – gbn

-1

Dado que siembra desde 1 e incrementa en 1 (IDENTIDAD (1,1)), me pregunto si puede crear un procedimiento donde puede establecer una variable como "Seleccionar @@ IDENTIDAD + 1" o algo así ese.

15

Probablemente desee utilizar SCOPE_IDENTITY no @@ IDENTITY para restringirlo al valor de identidad en el ámbito actual. Esto evita que los triggers inserten nuevos valores de identidad en otras tablas y no en la tabla en la que acaba de insertar.

Pero se puede calcular lo que el siguiente valor de identidad es

SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable 

El problema es que no se garantiza que es el valor. Debería tener un candado de tal manera que otras inserciones sean denegadas en la mesa cuando se ejecuta para garantizar que el valor sea preciso. Además, después de que te quedas sin enteros de 32 bits, no sé cuál es la lógica. No sé si se da vuelta o falla.

Edit: Acabo de probar esto (ver a continuación para SQL) y no devuelve el valor correcto cuando no hay datos. Y resiembra con DBCC CHECKIDENT ('nombre de tabla', RESEED, 200), en realidad resultó en el siguiente valor es 201 no 200.

CREATE TABLE willtest (myid integer IDENTITY(1,1), myvalue varchar(255)) 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

INSERT INTO willtest (myvalue) 
VALUES ('1') 
INSERT INTO willtest (myvalue) 
VALUES ('2') 
INSERT INTO willtest (myvalue) 
VALUES ('3') 
INSERT INTO willtest (myvalue) 
VALUES ('4') 
INSERT INTO willtest (myvalue) 
VALUES ('5') 
INSERT INTO willtest (myvalue) 
VALUES ('6') 
INSERT INTO willtest (myvalue) 
VALUES ('7') 
INSERT INTO willtest (myvalue) 
VALUES ('8') 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

DBCC CHECKIDENT ('willtest', RESEED, 200) 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

INSERT INTO willtest (myvalue) 
VALUES ('200') 
INSERT INTO willtest (myvalue) 
VALUES ('201') 
INSERT INTO willtest (myvalue) 
VALUES ('202') 
INSERT INTO willtest (myvalue) 
VALUES ('203') 
INSERT INTO willtest (myvalue) 
VALUES ('204') 
INSERT INTO willtest (myvalue) 
VALUES ('205') 
INSERT INTO willtest (myvalue) 
VALUES ('206') 
INSERT INTO willtest (myvalue) 
VALUES ('207') 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

SELECT * FROM willtest 

DROP TABLE willtest 
+0

En este punto, no podemos decidir si SCOPE_IDENTITY es más apropiado que @@ IDENTITY. O si estos son aplicables en absoluto. – MarlonRibunal

+0

Esa parte respondía a la sugerencia de casperOne. Ahora que la pregunta ha sido editada, el verdadero problema es más interesante. –

+0

no necesita 'FROM mytable' en su primera consulta –

-1

Uso GUID columnas para sus claves primarias. A menos que tenga miles de millones de registros y miles de solicitudes por segundo, probablemente no notará la diferencia en el rendimiento.Pero a menos que le guste pasar demasiado tiempo lidiando con problemas estúpidos como este, notará la diferencia en su nivel de estrés y esperanza de vida.

+1

I beg to differ; problemas de rendimiento pueden ocurrir incluso cuando hay cerca de cien mil registros y muy pocas solicitudes. Vea esta pregunta, por ejemplo: http://stackoverflow.com/questions/1703303/sum-group-performance-and-the-primary-key. Cambiamos de todo, desde identidades a GUIDs hace unos años y estamos empezando a arrepentirnos de este cambio ... – Heinzi

+2

Ahora, no use GUID como PK, a menos que 1. Sepa lo que está haciendo 2. No lo haga agrupado (vea el punto 1) – gbn

+0

en realidad no responde a la pregunta –

4

Esta pieza de SQL le dará el valor de columna al lado de identidad (es probable que haya muchas razones para no repetir este fragmento de código de producción)

declare @nextid int; 
declare @previousid int; 

begin tran 

insert into dbo.TestTable (Col1) values ('11'); 
select @nextid = SCOPE_IDENTITY(); 

rollback tran 

select @previousid = @nextid -1 
DBCC CHECKIDENT('dbo.TestTable', RESEED, @previousid); 
select @nextid 

esta pregunta StackOverflow da alguna información extra - sql-identity-autonumber-is-incremented-even-with-a-transaction-rollback

0
SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable 
+1

Esto no tiene en cuenta las filas eliminadas ... – HerbalMart

+0

Tampoco da cuenta de que alguien haya cambiado intencionalmente el siguiente número inicial, que es lo que sucede. interesado en hoy. –

+0

No estoy seguro de si esto es específico de una versión de base de datos, pero soy SQL Server 2008 R2, y el mío funcionó bien, respetó DBCC reseed y me dio los valores correctos. @HerbalMart Funciona en base a Ident_Current, y le proporciona valores correctos incluso si ha eliminado algunas filas. – Niraj

Cuestiones relacionadas