只有在使用列列表并且IDENTITY_INSERT为ON时才能指定表中标识列的显式值SQL Server

jho*_*owe 175 sql-server

我正在尝试进行此查询

INSERT INTO dbo.tbl_A_archive
  SELECT *
  FROM SERVER0031.DB.dbo.tbl_A
Run Code Online (Sandbox Code Playgroud)

但即使我跑了之后

set identity_insert dbo.tbl_A_archive on
Run Code Online (Sandbox Code Playgroud)

我收到此错误消息

只有在使用列列表且IDENTITY_INSERT为ON时,才能指定表'dbo.tbl_A_archive'中标识列的显式值.

tbl_A是一个巨大的行和宽度表,即它有很多列.我不想手动输入所有列.我怎样才能让它发挥作用?

小智 306

SET IDENTITY_INSERT tableA ON
Run Code Online (Sandbox Code Playgroud)

您必须为INSERT语句创建列列表:

INSERT Into tableA ([id], [c2], [c3], [c4], [c5] ) 
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB
Run Code Online (Sandbox Code Playgroud)

不喜欢"INSERT Into tableA SELECT ........"

SET IDENTITY_INSERT tableA OFF
Run Code Online (Sandbox Code Playgroud)

  • +1 ...您只需要查询的SELECT子句中的显式列.您可以在查询的INSERT子句中保留星号 (17认同)
  • ...除非目标具有标识列,并且源表没有标识列 (8认同)
  • +1就像一个魅力!但是,"您可以在查询的INSERT子句中保留星号"在此处不起作用. (4认同)

Hei*_*nzi 71

好吧,错误信息基本上都说明了一切.您有以下选择:

  • 创建一个列列表(INFORMATION_SCHEMA.COLUMNS上的SELECT和一个好的文本编辑器或Andomar和Dave提出的解决方案可以帮助你解决这个问题)

要么

  • tbl_A_archive常规(非标识)int列中创建标识列(因为它是一个存档表,为什么需要标识列?).

  • 这个细节还欠缺。我知道这对某些人来说可能是死记硬背,但对其他人来说却是无稽之谈 (2认同)

Dav*_*ray 38

如果您正在使用SQL Server Management Studio,则不必自己键入列列表 - 只需右键单击对象资源管理器中的表,然后选择脚本表作为 - > SELECT to - > New Query Editor Window.

如果不是,那么类似的查询应该有助于作为一个起点:

SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'tbl_A'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);
Run Code Online (Sandbox Code Playgroud)

  • 可以将其选择为变量并在动态SQL查询中使用.你救了我的一天.非常感谢! (2认同)

And*_*mar 21

同意Heinzi的回答.对于第一个选项,这是一个在表中生成以逗号分隔的列列表的查询:

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

对于大表,这可以节省大量的打字工作:)


Rob*_*Day 11

如果"存档"表是您主表的精确副本,那么我建议您删除id是一个标识列的事实.这样它会让你插入它们.

或者,您可以使用以下语句允许和禁止对表的标识插入

SET IDENTITY_INSERT tbl_A_archive ON
--Your inserts here
SET IDENTITY_INSERT tbl_A_archive OFF
Run Code Online (Sandbox Code Playgroud)

最后,如果您需要标识列按原样工作,那么您始终可以只运行存储过程.

sp_columns tbl_A_archive 
Run Code Online (Sandbox Code Playgroud)

这将返回表格中的所有列,然后您可以剪切并粘贴到查询中.(这几乎总比使用*更好)


Moh*_*ood 9

对于SQL语句,还必须指定列列表.例如.

INSERT INTO tbl (idcol1,col2) VALUES ( value1,value2)
Run Code Online (Sandbox Code Playgroud)

代替

INSERT INTO tbl VALUES ( value1,value2)
Run Code Online (Sandbox Code Playgroud)

  • OP的声明不是这种情况。如果INSERT INTO后跟SELECT语句,则不需要VALUES。请修改或删除您的答案。 (2认同)

Chi*_*kar 6

两者都可以使用,但如果使用 #1 仍然出错,则使用 #2

1)

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

2)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
VALUES(@Id,....)
Run Code Online (Sandbox Code Playgroud)

  • 如果 OP 插入多条记录,这真的不是办法。您忽略了“tbl_A 是一个巨大的行和宽表,即它有很多列。我不想手动输入所有列。” (4认同)