web-dev-qa-db-fra.com

Comment modifier les valeurs des colonnes d'identité par programme?

J'ai une base de données MS SQL 2005 avec une table Test avec la colonne ID. ID est une colonne d'identité.

J'ai des lignes dans cette table et toutes ont leur valeur incrémentée automatiquement d'identifiant correspondant.

Maintenant, je voudrais changer chaque ID dans cette table comme ceci:

ID = ID + 1

Mais quand je fais cela, je reçois une erreur:

Impossible de mettre à jour la colonne d'identité 'ID'.

J'ai essayé ceci:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

Mais cela ne résout pas le problème.

L'identité doit être définie dans cette colonne, mais je dois également modifier les valeurs de temps à autre. Ma question est donc de savoir comment accomplir cette tâche.

159
Tomasz Smykowski

Tu dois

set identity_insert YourTable ON

Supprimez ensuite votre ligne et réinsérez-la avec une identité différente.

Une fois que vous avez terminé l'insertion, n'oubliez pas de désactiver identity_insert

set identity_insert YourTable OFF
217
A-K

Les valeurs de la colonne IDENTITY sont immuables.

Cependant, il est possible de changer les métadonnées de la table pour supprimer la propriété IDENTITY, effectuer la mise à jour, puis revenir en arrière.

En supposant la structure suivante

CREATE TABLE Test
(
ID INT IDENTITY(1,1) PRIMARY KEY,
X VARCHAR(10)
)

INSERT INTO Test 
OUTPUT INSERTED.*
SELECT 'Foo' UNION ALL
SELECT 'Bar' UNION ALL
SELECT 'Baz'

Alors tu peux faire

/*Define table with same structure but no IDENTITY*/
CREATE TABLE Temp
(
ID INT PRIMARY KEY,
X VARCHAR(10)
)

/*Switch table metadata to new structure*/
ALTER TABLE Test SWITCH TO Temp;

/*Do the update*/
UPDATE Temp SET ID = ID + 1;

/*Switch table metadata back*/
ALTER TABLE Temp SWITCH TO Test;

/*ID values have been updated*/
SELECT *
FROM Test

/*Safety check in case error in preceding step*/
IF NOT EXISTS(SELECT * FROM Temp)
    DROP TABLE Temp /*Drop obsolete table*/

Dans SQL Server 2012, il est possible d'avoir une colonne à incrémentation automatique qui peut également être mise à jour plus simplement avec SEQUENCES

CREATE SEQUENCE Seq
    AS INT
    START WITH 1
    INCREMENT BY 1

CREATE TABLE Test2
(
ID INT DEFAULT NEXT VALUE FOR Seq NOT NULL PRIMARY KEY,
X VARCHAR(10)
)

INSERT INTO Test2(X)
SELECT 'Foo' UNION ALL
SELECT 'Bar' UNION ALL
SELECT 'Baz'

UPDATE Test2 SET ID+=1
40
Martin Smith

Dans l'interface utilisateur du gestionnaire SQL Server 2005, modifiez la colonne, supprimez la propriété numérotation automatique (identité) de la colonne (sélectionnez la table en cliquant dessus avec le bouton droit de la souris et choisissez "Conception").

Puis lancez votre requête:

UPDATE table SET Id = Id + 1

Puis, ajoutez la propriété autonumber à la colonne.

26
Michael Pryor

Premièrement, l'activation ou la désactivation de IDENTITY_INSERT ne fonctionnera pas pour ce que vous avez besoin (il est utilisé pour insérer de nouvelles valeurs, telles que le colmatage des espaces vides).

Effectuer l'opération via l'interface graphique crée simplement une table temporaire, copie toutes les données dans une nouvelle table sans champ d'identité et renomme la table.

18
Miles D

Cela peut être fait en utilisant une table temporaire.

L'idée

  • désactiver les contraintes (si votre identifiant est référencé par une clé étrangère)
  • créer une table temporaire avec le nouvel identifiant
  • supprimer le contenu du tableau
  • copier les données de la table copiée dans votre table d'origine
  • activer les contraintes précédemment désactivées

Requêtes SQL

Supposons que votre table test ait deux colonnes supplémentaires (column2 et column3) et qu'il existe deux tables contenant des clés étrangères référençant test et appelées foreign_table1 et foreign_table2 (car les problèmes de la vie réelle ne sont jamais simples).

alter table test nocheck constraint all;
alter table foreign_table1 nocheck constraint all;
alter table foreign_table2 nocheck constraint all;
set identity_insert test on;

select id + 1 as id, column2, column3 into test_copy from test v;
delete from test;
insert into test(id, column2, column3)
select id, column2, column3 from test_copy

alter table test check constraint all;
alter table foreign_table1 check constraint all;
alter table foreign_table2 check constraint all;
set identity_insert test off;
drop table test_copy;

C'est ça.

9

DBCC CHECKIDENT ('databasename.dbo.orders', RESEED, 999) vous pouvez modifier n’importe quel numéro de colonne d’identité avec cette commande, et vous pouvez également démarrer ce numéro de champ à partir de chaque numéro de votre choix. Par exemple, dans ma commande, je demande à partir de 1000 (999 + 1) espérons que cela suffira ... bonne chance

6
Roxana

Si la colonne n'est pas une clé PK, vous pouvez toujours créer une nouvelle colonne dans la table avec les numéros incrémentés, supprimer l'original, puis remplacer le nouveau par l'ancien.

curieux de savoir pourquoi vous pourriez avoir besoin de faire cela… la plupart des choses que j'ai jamais eues avec des colonnes Identity étaient de renvoyer des numéros et je venais juste d'utiliser DBCC CHECKIDENT (nom_table, RESEED, newnextnumber)

bonne chance!

4
Christopher Klein

La modification de l'identité peut échouer en fonction d'un certain nombre de facteurs, principalement autour des objets/relations liés à la colonne id. Il semble que la conception de la base de données pose le même problème, car les identifiants ne devraient que rarement, voire jamais, changer (je suis sûr que vous avez vos raisons et que vous modifiez les modifications). Si vous avez vraiment besoin de changer d'identifiant de temps en temps, je vous suggèrerais de créer une nouvelle colonne d'identifiant factice qui ne soit pas la clé primaire/le numéro automatique que vous pouvez gérer vous-même et générer à partir des valeurs actuelles. Alternativement, l'idée de Chrisotphers ci-dessus serait mon autre suggestion si vous rencontrez des problèmes avec l'autorisation d'insertion d'identité.

Bonne chance

Post-scriptum cela ne échoue pas parce que l'ordre séquentiel dans lequel il s'exécute tente de mettre à jour une valeur de la liste vers un élément qui existe déjà dans la liste des identifiants? en saisissant des pailles, peut-être ajouter le nombre de lignes + 1, puis si cela fonctionne soustraire le nombre de lignes: -S

1
Tanner

Commencez par enregistrer tous les identifiants et modifiez-les par programmation pour les transformer en valeurs, puis supprimez-les de la base de données, puis insérez-les à nouveau à l'aide de quelque chose de similaire:

use [Name.Database]
go
set identity_insert [Test] ON
insert into [dbo].[Test]
           ([Id])
     VALUES
           (2)
set identity_insert [Test] OFF

Pour l'utilisation d'insert en vrac:

use [Name.Database]
go
set identity_insert [Test] ON
BULK INSERT [Test]
FROM 'C:\Users\Oscar\file.csv'
WITH (FIELDTERMINATOR = ';',
      ROWTERMINATOR = '\n',
      KEEPIDENTITY)
set identity_insert [Test] OFF

Exemple de données de fichier.csv:

2;
3;
4;
5;
6;

Si vous ne désactivez pas identity_insert, vous obtiendrez l'erreur suivante:

Impossible d'insérer une valeur explicite pour la colonne d'identité dans la table 'Test' lorsque IDENTITY_INSERT est défini sur OFF.

1
Ogglas

Si vous devez modifier les identifiants à l'occasion, il est probablement préférable de ne pas utiliser de colonne d'identité. Dans le passé, nous avons implémenté manuellement les champs de numérotation automatique à l'aide d'une table 'Compteurs' qui permet de suivre l'ID suivant pour chaque table. C'est ce que nous avons fait le IIRC, car les colonnes d'identité causaient une corruption de la base de données dans SQL2000, mais il était parfois utile de pouvoir modifier les identifiants.

1
Robin Bennett

Vous pouvez insérer de nouvelles lignes avec des valeurs modifiées, puis supprimer les anciennes. L'exemple suivant d'ID de modification est identique à la clé étrangère PersonId

SET IDENTITY_INSERT [PersonApiLogin] ON

INSERT INTO [PersonApiLogin](
       [Id]
      ,[PersonId]
      ,[ApiId]
      ,[Hash]
      ,[Password]
      ,[SoftwareKey]
      ,[LoggedIn]
      ,[LastAccess])
SELECT [PersonId]
      ,[PersonId]
      ,[ApiId]
      ,[Hash]
      ,[Password]
      ,[SoftwareKey]
      ,[LoggedIn]
      ,[LastAccess]
FROM [db304].[dbo].[PersonApiLogin]
GO

DELETE FROM [PersonApiLogin]
WHERE [PersonId] <> ID
GO
SET IDENTITY_INSERT [PersonApiLogin] OFF
GO
1
Tomas Kubes

J'ai vu un bon article qui m'a aidé au dernier moment. J'essayais d'insérer quelques lignes dans un tableau comportant une colonne d'identité, mais je l'avais mal fait et je devais le supprimer. Une fois que j'ai supprimé les lignes, ma colonne d'identité a été modifiée. J'essayais de trouver un moyen de mettre à jour la colonne qui avait été insérée mais - pas de chance. Ainsi, lors de la recherche sur Google a trouvé un lien ..

  1. Supprimé les colonnes mal insérées
  2. Utiliser la force en utilisant l’identité activée/désactivée (expliqué ci-dessous)

http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column- comment-puis-je-mettre à jour la valeur d'un an.aspx

0
Balu

Très belle question, nous devons d’abord sur l’IDENTITY_INSERT de la table spécifique, puis exécuter la requête d’insertion (Doit spécifier le nom de la colonne).

Remarque: Après avoir édité la colonne d'identité, n'oubliez pas de off le IDENTITY_INSERT. Si vous ne l'avez pas fait, vous ne pouvez pas modifier la colonne d'identité pour une autre table.

SET IDENTITY_INSERT Emp_tb_gb_Menu ON
     INSERT Emp_tb_gb_Menu(MenuID) VALUES (68)
SET IDENTITY_INSERT Emp_tb_gb_Menu OFF

http://allinworld99.blogspot.com/2016/07/how-to-edit-identity-field-in-sql.html

0
Asith Raj