我试着做这个查询

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

但即使在我跑了之后

set identity_insert dbo.tbl_A_archive on

我得到这个错误消息

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

tbl_A是一个行和宽都很大的表,也就是说它有很多列。我不想手动输入所有的列。我怎样才能让它工作呢?


当前回答

这应该有用。我刚碰到你的问题

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;

不幸的是,似乎您确实需要包含标识列的列列表来插入指定标识的记录。但是,您不必在SELECT中列出列。 正如@Dave Cluderay建议的那样,这将导致一个格式化的列表供您复制和粘贴(如果小于200000字符)。

我添加了USE,因为我要在实例之间切换。

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);

其他回答

此代码片段显示当标识主键列为ON时如何插入到表中。

SET IDENTITY_INSERT [dbo].[Roles] ON
GO
insert into Roles (Id,Name) values(1,'Admin')
GO
insert into Roles (Id,Name) values(2,'User')
GO
SET IDENTITY_INSERT [dbo].[Roles] OFF
GO

两者都可以工作,但如果使用#1仍然会出错,那么就使用#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,....)

为了将所有列名填充到这个问题的解决方案的Select语句的逗号分隔列表中,我使用了以下选项,因为它们比这里的大多数响应更简洁。然而,这里的大多数回答仍然是完全可以接受的。

1)

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

2)这可能是创建列最简单的方法, 如果你有SQL Server SSMS。

1)在对象资源管理器中打开表,单击表名左侧的“+”或双击表名打开子列表。 2)将列子文件夹拖到主查询区,它将为您自动生成整个列列表。

总结

SQL Server不允许您在标识列中插入显式值,除非您使用列列表。因此,你有以下选项:

制作一个列列表(手动或使用工具,见下文)

OR

将tbl_A_archive中的标识列设置为常规的非标识列:如果您的表是一个归档表,并且总是为标识列显式指定一个值,那么为什么还需要标识列呢?只需要使用常规int型就可以了。


方案一详细说明

而不是

SET IDENTITY_INSERT archive_table ON;

INSERT INTO archive_table
  SELECT *
  FROM source_table;

SET IDENTITY_INSERT archive_table OFF;

你需要写

SET IDENTITY_INSERT archive_table ON;

INSERT INTO archive_table (field1, field2, ...)
  SELECT field1, field2, ...
  FROM source_table;

SET IDENTITY_INSERT archive_table OFF;

用field1, field2,…包含表中所有列的名称。如果您想自动生成列列表,请查看Dave的答案或Andomar的答案。


方案二详细说明

不幸的是,仅仅将单位int列的“类型”更改为非单位int列是不可能的。基本上,你有以下几种选择:

如果存档表还不包含数据,则删除该列并添加一个不带标识的新列。

OR

使用SQL Server Management Studio将存档表中的标识列的标识规范/(是标识)属性设置为No。在幕后,这将创建一个脚本来重新创建表并复制现有数据,因此,要做到这一点,您还需要取消设置Tools/Options/Designers/ table和Database Designers/Prevent保存需要重新创建表的更改。

OR

使用此回答中描述的解决方法之一:从表中的列中删除标识

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

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

而不是

INSERT INTO tbl VALUES ( value1,value2)