2009-02-18 7 views
7

Existe-t-il une requête tsql indiquant la valeur de colonne d'identité du serveur SQL qu'il s'attend à utiliser pour l'insertion de ligne suivante?Comment dites-vous quelle sera la prochaine colonne d'identité?

Edité à ajouter:

J'ai supprimé et recréé une table dans le cadre de ma commande CREATE TABLE avec

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

. J'ai également essayé de réanimer des colonnes d'identité en supprimant toutes les informations de cette table et cela n'a pas toujours fonctionné. Cela m'a amené à me demander s'il y avait un moyen de voir ce que SQL s'attendait à utiliser pour votre prochain numéro de colonne d'identité.

+0

Pas que je sache, mais pourquoi voulez-vous savoir? Quel est le problème de la grande image? – colithium

+0

Si vous voulez un vidage rapide de la table, 'truncate table' reseeds automatiquement toutes les colonnes d'identité – SWeko

Répondre

10

Non, il n'y a aucun moyen garantie (bien que vous pouvez certainement savoir ce que la prochaine valeur pourrait être, une autre commande peut aller l'utiliser avant de pouvoir faire usage de celui-ci). La seule valeur garantie que vous pouvez récupérer est précédemment valeur d'identité insérée à travers SCOPE_IDENTITY() (qui retournera la valeur d'identité générée en dernier pour la portée actuelle).

On peut se demander dans quel but il faudrait connaître la valeur avant (lorsqu'on utilise une colonne d'identité ensemencée automatiquement incrémentée).

Si vous avez besoin de connaître la valeur avant, je vous recommande de générer les identifiants vous-même. Vous pouvez le faire avec une table d'IDs sur le nom de la table, ou, si vous avez des problèmes d'évolutivité (et vous utilisez des transactions), vous pouvez avoir une table d'ID pour chaque table qui a besoin d'un identifiant. et ensuite incrémenté). Ou, vous pourriez utiliser un GUID, et vous seriez capable de les générer facilement du côté client avant de l'envoyer à votre base de données.

+0

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

-1

Puisque vous semez de 1 et augmentez de 1 (IDENTITY (1,1)), je me demande si vous pouvez créer une procédure où vous pouvez définir une variable comme "Select @@ IDENTITY + 1" ou quelque chose comme cette.

15

Vous souhaitez probablement utiliser SCOPE_IDENTITY pas @@ IDENTITY pour le restreindre à la valeur d'identité dans la portée actuelle. Cela évite d'insérer de nouvelles valeurs d'identité par des déclencheurs dans d'autres tables et non dans la table que vous venez d'insérer.

Mais vous pouvez calculer ce que la valeur d'identité est

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

Le problème est que vous n'êtes pas garanti que la valeur est. Vous devez disposer d'un verrou tel que les autres insertions sont refusées sur la table lors de son exécution pour garantir la précision de la valeur. Aussi, après avoir épuisé les entiers de 32 bits, je ne sais pas quelle est la logique. Je ne sais pas si ça roule ou échoue.

Editer: Je viens de tester cela (voir ci-dessous pour SQL) et il ne retourne pas la valeur correcte lorsqu'il n'y a pas de données. Et réensemencement avec DBCC CHECKIDENT ('tablename', RESEED, 200) en fait a donné lieu à la valeur suivante étant 201 non 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

À ce stade, nous ne pouvons même pas décider si SCOPE_IDENTITY est plus approprié que @@ IDENTITY. Ou si ceux-ci sont applicables du tout. – MarlonRibunal

+0

Cette partie répondait à la suggestion de casperOne. Maintenant que la question a été éditée - le vrai problème est plus intéressant. –

+0

vous n'avez pas besoin de 'FROM mytable' dans votre première requête –

-1

Utilisez GUID colonnes pour vos clés primaires. À moins d'avoir des milliards d'enregistrements et des milliers de requêtes par seconde, vous ne remarquerez probablement pas la différence de performance.Mais à moins de vouloir passer beaucoup trop de temps à traiter des problèmes stupides comme celui-ci, vous remarquerez la différence entre votre niveau de stress et votre espérance de vie.

+1

Je demande à différer; Des problèmes de performance peuvent survenir même s'il y a environ cent mille enregistrements et très peu de demandes. Voir cette question, par exemple: http://stackoverflow.com/questions/1703303/sum-group-performance-and-the-primary-key. Nous avons tout transféré des identités aux GUID il y a quelques années et nous commençons à regretter ce mouvement ... – Heinzi

+2

Maintenant, n'utilisez pas le GUID comme PK sauf si vous 1. Sachez ce que vous faites 2. Ne le faites pas clustered (voir le point 1) – gbn

+0

ne répond pas réellement à la question –

4

Ce morceau de sql vous donnera la valeur de colonne d'identité suivante (il y a probablement de nombreuses raisons de ne pas répéter cet extrait dans le code de production)

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 

cette question stackoverflow donne des informations supplémentaires - sql-identity-autonumber-is-incremented-even-with-a-transaction-rollback

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

Cela ne tient pas compte des lignes supprimées ... – HerbalMart

+0

Il ne tient pas compte non plus de quelqu'un ayant intentionnellement changé le numéro de la semence suivante, ce qui est ce que je suis intéressé par aujourd'hui. –

+0

Je ne suis pas sûr si cela est spécifique à une version de base de données, mais je suis SQL Server 2008 R2, et le mien a bien fonctionné, il a honoré DBCC reseed, et m'a donné les valeurs correctes. @HerbalMart Fonctionne sur Ident_Current et vous donne des valeurs correctes même si vous avez supprimé certaines lignes. – Niraj

Questions connexes