web-dev-qa-db-fra.com

Une valeur explicite pour la colonne d'identité dans la table ne peut être spécifiée que lorsqu'une liste de colonnes est utilisée et que IDENTITY_INSERT est ON SQL Server.

J'essaie de faire cette requête 

INSERT INTO     dbo.tbl_A_archive
SELECT  *
FROM        SERVER0031.DB.dbo.tbl_A

mais même après avoir couru

set identity_insert dbo.tbl_A_archive on

Je reçois ce message d'erreur 

Une valeur explicite pour la colonne d'identité de la table 'dbo.tbl_A_archive' ne peut être spécifiée que lorsqu'une liste de colonnes est utilisée et que IDENTITY_INSERT est activé.

tbl_A est une table énorme en lignes et en largeur, c’est-à-dire qu’elle contient BEAUCOUP de colonnes. Je ne veux pas avoir à taper toutes les colonnes manuellement. Comment puis-je obtenir que cela fonctionne? 

154
jhowe

Eh bien, le message d'erreur dit tout. Vous avez les options suivantes:

  • Faites une liste de colonnes (un SELECT sur INFORMATION_SCHEMA.COLUMNS et un bon éditeur de texte ou les solutions proposées par Andomar et Dave peuvent vous aider avec cela)

OR

  • faites de la colonne d'identité dans tbl_A_archive une colonne int régulière (non-identité) (puisqu'il s'agit d'une table d'archivage, pourquoi avez-vous besoin d'une colonne d'identité?).
64
Heinzi
SET IDENTITY_INSERT tableA ON

Vous devez créer une liste de colonnes pour votre instruction INSERT:

INSERT Into tableA ([id], [c2], [c3], [c4], [c5] ) 
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB

pas comme "INSERER dans la tableA SELECT ........"

SET IDENTITY_INSERT tableA OFF
277
Ehsan

Si vous utilisez SQL Server Management Studio, vous n'avez pas besoin de taper la liste des colonnes vous-même. Cliquez avec le bouton droit de la souris sur la table dans Object Explorer et choisissez Script Table comme -> SELECT pour -> Nouvelle fenêtre de l'éditeur de requête .

Si ce n'est pas le cas, une requête semblable à celle-ci devrait vous aider comme point de départ:

SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'tbl_A'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);
33
Dave Cluderay

D'accord avec la réponse de Heinzi. Pour la seconde option, voici une requête qui génère une liste de colonnes séparées par une virgule dans une table:

select name + ', ' as [text()] 
from sys.columns 
where object_id = object_id('YourTable') 
for xml path('')

Pour les grandes tables, cela peut économiser beaucoup de travail de frappe :)

16
Andomar

Si la table "archive" est censée être une copie exacte de votre table principale, je vous suggère simplement de supprimer le fait que l'identifiant est une colonne identiy De cette façon, vous pourrez les insérer.

Sinon, vous pouvez autoriser et interdire les insertions d'identité pour la table avec l'instruction suivante.

SET IDENTITY_INSERT tbl_A_archive ON
--Your inserts here
SET IDENTITY_INSERT tbl_A_archive OFF

Enfin, si vous avez besoin que la colonne d’identité fonctionne telle quelle, vous pouvez toujours exécuter le proc stocké.

sp_columns tbl_A_archive 

Cela vous retournera toutes les colonnes de la table que vous pourrez ensuite couper et coller dans votre requête. (C'est presque TOUJOURS mieux que d'utiliser un *)

10
Robin Day

Pour l'instruction SQL, vous devez également spécifier la liste des colonnes. Pour par exemple.

INSERT INTO tbl (idcol1,col2) VALUES ( value1,value2)

au lieu de

INSERT INTO tbl VALUES ( value1,value2)
7
mohsinmdl

Afin de renseigner tous les noms de colonne dans une liste délimitée par des virgules pour une instruction Select des solutions mentionnées pour cette question, j'utilise les options suivantes, car elles sont un peu moins explicites que celles d'Andomar. Andomar est toujours parfaitement acceptable. 

1)

SELECT column_name + ',' 
FROM   information_schema.columns 
WHERE  table_name = 'YourTable'

2) Il s'agit probablement de l'approche la plus simple pour créer des colonnes, Si vous avez SQL Server SSMS.

1) Accédez à la table dans l'Explorateur d'objets et cliquez sur le signe + situé à gauche du nom de la table ou double-cliquez sur le nom de la table pour ouvrir la liste secondaire. 

2) Faites glisser le sous-dossier de colonne sur la zone de requête principale et la copie automatique de la liste complète des colonnes sera automatiquement effectuée. 

2
Ryan

Les deux fonctionneront, mais si vous avez toujours Si vous obtenez une erreur en utilisant # 1 alors allez pour # 2

1)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
SELECT Id, ...
FROM SERVER0031.DB.dbo.tbl_A

2)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
VALUES(@Id,....)

Bonne journée.

2
Chirag Thakar

Cela devrait marcher. Je viens de rencontrer votre problème:

SET IDENTITY_INSERT dbo.tbl_A_archive ON;
INSERT INTO     dbo.tbl_A_archive (IdColumn,OtherColumn1,OtherColumn2,...)
SELECT  *
FROM        SERVER0031.DB.dbo.tbl_A;
SET IDENTITY_INSERT dbo.tbl_A_archive OFF;

Malheureusement, il semble que vous ayez besoin d'une liste des colonnes, y compris la colonne identité, pour insérer des enregistrements spécifiant l'identité. Cependant , vous n'avez PAS à lister les colonnes du SELECT . Comme @ Dave Cluderay l'a suggéré, cela donnera une liste formatée que vous pourrez copier et coller (si moins de 200000 caractères ). 

J'ai ajouté le USE depuis que je bascule entre les instances.

USE PES
SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'Provider'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);
1
Gary

Vous devez spécifier le nom de colonne que vous souhaitez insérer s'il existe une colonne Identity. Ainsi, la commande sera comme ci-dessous:

SET IDENTITY_INSERT DuplicateTable ON

INSERT Into DuplicateTable ([IdentityColumn], [Column2], [Column3], [Column4] ) 
SELECT [IdentityColumn], [Column2], [Column3], [Column4] FROM MainTable

SET IDENTITY_INSERT DuplicateTable OFF

Si votre table a plusieurs colonnes, obtenez le nom de ces colonnes en utilisant cette commande.

SELECT column_name + ','
FROM   information_schema.columns 
WHERE  table_name = 'TableName'
for xml path('')

(après avoir supprimé la dernière virgule (',')) Copiez simplement le nom des colonnes précédentes.

1
Md. Rousonur Jaman

Cette image montre comment insérer dans une table lorsque la colonne de clé primaire d'identité est activée. [Insert to Table When Identity Primary Key Column.] [Insérer dans le tableau lorsque la colonne de clé primaire d’identité]

0
AminGolmahalle

Cette image montre comment insérer dans une table lorsque la colonne de la clé primaire d'identité est activée.

 Sample IDENTITY_INSERT

0
AminGolmahalle

Car si vous souhaitez insérer vos valeurs d'une table à une autre via une procédure stockée. J'ai utilisé this et this , ce dernier est presque comme la réponse d'Andomar.

CREATE procedure [dbo].[RealTableMergeFromTemp]
    with execute as owner
AS
BEGIN
BEGIN TRANSACTION RealTableDataMerge
SET XACT_ABORT ON

    DECLARE @columnNameList nvarchar(MAX) =
     STUFF((select ',' + a.name
      from sys.all_columns a
      join sys.tables t on a.object_id = t.object_id 
       where t.object_id = object_id('[dbo].[RealTable]') 
    order by a.column_id
    for xml path ('')
    ),1,1,'')

    DECLARE @SQLCMD nvarchar(MAX) =N'INSERT INTO [dbo].[RealTable] (' + @columnNameList + N') SELECT * FROM [#Temp]'

    SET IDENTITY_INSERT [dbo].[RealTable] ON;
    exec(@sqlcmd)
    SET IDENTITY_INSERT [dbo].[RealTable] OFF

COMMIT TRANSACTION RealTableDataMerge
END

GO
0
Rubenisme