2009-06-12 7 views
4

Je rencontre un problème étrange, et j'ai besoin d'aide pour essayer de le comprendre.Sql Server 2005 violation de clé primaire sur une colonne d'identité

J'ai une base de données qui a une colonne ID (définie comme int null, Identity, commence à 1, incrémente de 1) en plus de toutes les colonnes de données d'application. La clé primaire de la table est la colonne ID, pas d'autres composants.

Il n'y a pas d'ensemble de données que je puisse utiliser en tant que «clé primaire naturelle» puisque l'application doit permettre plusieurs soumissions de données identiques.

je une procédure stockée, qui est la seule façon d'ajouter de nouveaux enregistrements dans la table (autres que la connexion au serveur directement en tant que propriétaire db)

Alors que QA testait l'application ce matin, ils à entrer un nouvel enregistrement dans la base de données (en utilisant l'application comme il était prévu, et comme ils l'ont fait pendant les deux dernières semaines) et a rencontré une violation de clé primaire sur cette table.

C'est de la même manière que je fais les clefs primaires depuis environ 10 ans maintenant, et n'ai jamais couru à travers ceci.

Des idées pour résoudre ce problème? Ou est-ce un de ces problèmes de rayons cosmiques qui apparaissent une fois de temps en temps.

Merci pour tout conseil que vous pouvez donner.

Nigel

Edité à 13h15 HAE 12 Juin pour donner plus d'informations

Une version simplifiée du schéma ...

CREATE TABLE [dbo].[tbl_Queries](
[QueryID] [int] IDENTITY(1,1) NOT NULL, 
[FirstName] [varchar](50) NOT NULL, 
[LastName] [varchar](50) NOT NULL, 
[Address] [varchar](150) NOT NULL, 
[Apt#] [varchar](10) NOT NULL 
    ... <12 other columns deleted for brevity> 
[VersionCode] [timestamp] NOT NULL, 
CONSTRAINT [PK_tbl_Queries] PRIMARY KEY CLUSTERED 
(
    [QueryID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

(également supprimé les déclarations de valeur par défaut) La procédure stockée est la suivante:

insert into dbo.tbl_Queries 
    ( FirstName, 
     LastName, 
     [Address], 
     [Apt#]...) values 
    ( @firstName, 
     @lastName, 
     @address, 
     isnull(@apt, ''), ...) 

Il ne regarde même pas la colonne d'identité, n'utilise pas IDENTITY, @@ scope_identity ou quelque chose de similaire, c'est juste un fichier et oubliez.

Je suis aussi confiant que possible que la valeur d'identité n'a pas été réinitialisée et que personne d'autre n'utilise l'accès direct à la base de données pour entrer des valeurs. La seule fois dans ce projet que l'insertion d'identité est utilisée est dans le déploiement de base de données initiale pour définir des valeurs spécifiques dans les tables de recherche.

L'équipe de contrôle qualité a réessayé après avoir reçu l'erreur et a réussi à soumettre une requête. Depuis, elle tente de la reproduire et n'a pas réussi jusqu'à présent.

J'apprécie vraiment les idées des gens.

+0

Hmmm ... est-il possible de coller un schéma de table aseptisé et/ou l'instruction d'insertion incriminée? – ristonj

+0

Êtes-vous toujours incapable d'ajouter de nouveaux enregistrements, ou est-ce que cela ne s'est produit qu'une seule fois? –

+0

vérifier ma réponse ci-dessous Nigel ... – Eric

Répondre

1

pensée aléatoire basé sur l'expérience

Avez-vous des données avec synched, par exemple, Comparer Red Gate Data. Cela a une option pour réanimer les colonnes d'identité. Cela a causé des problèmes à utiliser. Et un autre projet le mois dernier.

Vous pouvez également avoir des ID explicitement chargés/synchronisés.

+0

Non, cela s'est produit sur une base de données d'installation spécifiquement pour le contrôle de la qualité il y a environ deux semaines. La base de données a été déployée à partir de VSTS Team Suite, édition 2008, et remplie avec 500 enregistrements générés. Depuis lors, ils ont ajouté environ 50 enregistrements avant et après le rapport de problème. – Nigel

+0

Quelqu'un a couru le DBCC CHECKIDENT ou SET IDENTITY_INSERT ON puis – gbn

4

Bien que je n'ai pas d'explication quant à une cause potentielle, il est certinalement possible de changer la valeur initiale d'une colonne d'identité. Si la graine était abaissée à l'endroit où la valeur suivante existerait déjà dans le tableau, cela pourrait certainement causer ce que vous voyez. Essayez de courir DBCC CHECKIDENT (table_name) et voir ce qu'il vous donne.

Pour plus d'informations, consultez this page

+0

Oui, c'était aussi ma première réaction instinctive - la table a probablement été jouée avec et la valeur IDENTITY a été réinitialisée ou quelque chose. –

+1

Ou quelqu'un a inséré des valeurs dans la table avec l'option SET IDENTITY_INSERT ON activée. –

+0

Merci Adam, je n'étais pas au courant de cette commande, cependant, cela n'a pas aidé. Il a signalé la valeur actuelle comme 550, et la valeur maximale de la colonne comme 550, et cela correspond à ce que je vois. – Nigel

6

Sons comme la graine d'identité a été corrompu ou remis à zéro en quelque sorte. solution la plus simple sera de réinitialiser la graine à la valeur actuelle max de la colonne d'identité:

DECLARE @nextid INT; 
SET @nextid = (SELECT MAX([columnname]) FROM [tablename]); 
DBCC CHECKIDENT ([tablename], RESEED, @nextid); 
+1

Avez-vous essayé de le faire vous-même? Déjà? – gbn

+1

Je n'ai pas testé ma déclaration, donc je l'ai réécrit –

+0

Je voudrais seconder celui-ci. Je ne vois aucun moyen de dupliquer les valeurs sauf si la graine a été annulée. Je suppose que la corruption aurait pu se produire, mais j'ai utilisé SQL pendant 10 ans et je n'ai vu la corruption qu'une seule fois dans un scénario à faible espace disque –

0

Peut-être que quelqu'un d'insérer des enregistrements de journalisation dans le serveur en utilisant directement un nouvel ID explicity, puis lorsque le champ d'incrémentation automatique d'identité atteindre ce numéro une violation de clé primaire s'est produite.

Mais le rayon cosmique est algo une bonne explication;)

0

Juste pour très, très sûr ... vous n'utilisez pas IDENTITY_INSERT dans votre procédure stockée êtes-vous? Une certaine logique comme ceci:

declare @id int; 
Set @id=Select Max(IDColumn) From Sometable; 
SET IDENTITY_INSERT dbo.SomeTable ON 
Insert (IDColumn, ...others...) Values (@id+1, ...others...); 
SET IDENTITY_INSERT dbo.SomeTable OFF 
. 
. 
. 

Je me sens collant juste en le tapant. Mais de temps en temps vous rencontrez des gens qui n'ont jamais vraiment compris ce qu'est une colonne Identité et je veux m'assurer que c'est exclu. En passant: si c'est la réponse, je ne vous en tiendrai pas rigueur si vous supprimez simplement la question et n'admettez jamais que c'était votre problème! Pouvez-vous dire que j'embauche des stagiaires tous les étés?

+0

Oui, j'ai vérifié, et il n'y a pas IDENTITY_INSERT dans les procs stockés. Le seul endroit que j'ai trouvé était dans les requêtes initiales qui sont exécutées pour remplir les données de recherche (différentes tables que celle avec le problème). – Nigel

0

Utilisez-vous des fonctions telles que @@ identity ou scope_identity() dans l'une de vos procédures? si votre table a des déclencheurs ou plusieurs inserts vous pourriez obtenir en arrière la valeur fausse identité pour la table que vous voulez

+0

Cela entraînerait une corruption de données, mais pas une violation de clé primaire dans la table avec la colonne d'identité, sauf s'il insère des valeurs d'identité explicites. –

0

La violation de clé primaire ne provient pas nécessairement de cette table.

L'application touche-t-elle d'autres tables ou appelle-t-elle d'autres procédures stockées pour cette fonction? Y a-t-il des déclencheurs sur la table? Ou la procédure stockée elle-même utilise-t-elle d'autres tables ou procédures stockées? En particulier, une table ou un déclencheur d'audit peut provoquer cette erreur.

+0

Le message d'erreur que nous avons reçu du serveur indiquait que c'était cette table qui lançait l'erreur. La procédure stockée ne touche aucune autre table ou n'appelle pas une autre procédure stockée. Il existe un déclencheur de mise à jour, mais la première chose à faire est de vérifier s'il s'agit réellement d'une mise à jour (c'est-à-dire que la table pseudo supprimée n'est pas vide). Je pense que je vais faire une craie aux rayons cosmiques (mon manager est d'accord sur le fait que puisque ce n'est pas reproductible, nous pouvons l'ignorer à moins qu'il ne revienne). – Nigel

Questions connexes