Sql server 只有在使用列列表且identity_INSERT位于SQL Server上时,才能为表中的identity列指定显式值
我正在尝试做这个查询Sql server 只有在使用列列表且identity_INSERT位于SQL Server上时,才能为表中的identity列指定显式值,sql-server,Sql Server,我正在尝试做这个查询 INSERT INTO dbo.tbl_A_archive SELECT * FROM SERVER0031.DB.dbo.tbl_A 但即使在我跑步之后 set identity_insert dbo.tbl_A_archive on 我收到了这个错误消息 只有在使用列列表且“identity_INSERT”处于启用状态时,才能为表“dbo.tbl_A_archive”中的identity列指定显式值 tbl_A是一个行数和宽度都很大的表,即它有很多列。我不想
INSERT INTO dbo.tbl_A_archive
SELECT *
FROM SERVER0031.DB.dbo.tbl_A
但即使在我跑步之后
set identity_insert dbo.tbl_A_archive on
我收到了这个错误消息
只有在使用列列表且“identity_INSERT”处于启用状态时,才能为表“dbo.tbl_A_archive”中的identity列指定显式值
tbl_A
是一个行数和宽度都很大的表,即它有很多列。我不想手动键入所有列。我怎样才能让它工作 摘要
SQL Server不允许您在标识列中插入显式值,除非您使用列列表。因此,您有以下选项:
tbl_A_archive
中的标识列设置为常规的非标识列:如果您的表是一个归档表,并且您总是为标识列指定一个显式值,为什么您甚至需要标识列?只需使用一个普通的int解决方案1的详细信息
SELECT column_name + ','
FROM information_schema.columns
WHERE table_name = 'YourTable'
而不是
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、…
。如果要自动生成该列列表,请查看或
解决方案2的详细信息 不幸的是,不可能只将identity int列的“类型”更改为非identity int列。基本上,您有以下选项:
- 如果存档表尚未包含数据,请删除该列并添加一个不带标识的新列
- 使用SQL Server Management Studio将存档表中标识列的
/标识规范
属性设置为(Is Identity)
。在幕后,这将创建一个脚本来重新创建表并复制现有数据,因此,要做到这一点,您还需要取消设置否
/工具
/选项
/设计器
/表和数据库设计器
防止保存需要重新创建表的更改
- 使用此答案中描述的解决方法之一:
SET IDENTITY_INSERT tbl_A_archive ON
--Your inserts here
SET IDENTITY_INSERT tbl_A_archive OFF
最后,如果您需要标识列按原样工作,那么您可以始终只运行存储的过程
sp_columns tbl_A_archive
这将返回表中的所有列,然后可以将这些列剪切并粘贴到查询中。(这几乎总是比使用*)如果您使用的是SQL Server Management Studio,您不必自己键入列列表-只需在对象资源管理器中右键单击该表,然后选择脚本表作为->选择以->新建查询编辑器窗口 如果您不是,那么类似于此的查询将有助于作为起点:
SELECT SUBSTRING(
(SELECT ', ' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tbl_A'
ORDER BY ORDINAL_POSITION
FOR XML path('')),
3,
200000);
同意海因茨的回答。对于第一个选项和第二个选项,下面是一个查询,该查询生成表中以逗号分隔的列列表:
select name + ', ' as [text()]
from sys.columns
where object_id = object_id('YourTable')
for xml path('')
对于大表,这可以节省大量的键入工作:)
您必须为INSERT语句创建列列表:
INSERT Into tableA ([id], [c2], [c3], [c4], [c5] )
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB
不像“插入到表格中选择……”
两者都可以工作,但如果使用#1仍然会出错,则使用#2 (一) (二)
为了将所有列名填充到一个逗号分隔的列表中,以便为这个问题提到的解决方案生成Select语句,我使用了以下选项,因为它们比这里的大多数回答稍微不冗长。尽管如此,这里的大多数回答仍然是完全可以接受的 1) 2)这可能是创建列的最简单方法, 如果您有SQL Server SSM 1) 转到对象资源管理器中的表,单击表名左侧的+或双击表名以打开子列表 2) 将列子文件夹拖到主查询区域,它将为您自动粘贴整个列列表
如果存在标识列,则必须指定要插入的列名称。 因此,命令如下所示:
SET IDENTITY_INSERT DuplicateTable ON
INSERT Into DuplicateTable ([IdentityColumn], [Column2], [Column3], [Column4] )
SELECT [IdentityColumn], [Column2], [Column3], [Column4] FROM MainTable
SET IDENTITY_INSERT DuplicateTable OFF
如果您的表有许多列,则使用此命令获取这些列的名称
SELECT column_name + ','
FROM information_schema.columns
WHERE table_name = 'TableName'
for xml path('')
(删除最后一个逗号(“,”)后,只需复制过去的列名。对于SQL语句,还必须指定列列表。例如
INSERT INTO tbl (idcol1,col2) VALUES ( value1,value2)
而不是
INSERT INTO tbl VALUES ( value1,value2)
我认为发生此错误的原因是表定义中的列数和insert查询中的列数不匹配。此外,输入的值将省略列的长度。
因此,只需查看表定义即可解决此问题这应该是可行的。我刚刚遇到了你的问题:
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;
不幸的是,您似乎确实需要一个列列表,包括标识列,以插入指定标识的记录但是,您不必在选择列表中列出列。
正如@Dave Cluderay所建议的,这将产生一个格式化列表,供您复制和粘贴(如果少于200000个字符)
我添加了这个用法,因为我在实例之间切换
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);
此代码段显示了在启用标识主键列时如何插入到表中
SET IDENTITY\u在上插入[dbo].[Roles]
去
插入角色(Id、名称)值(1,'Admin')
去
插入角色(Id、名称)值(2,“用户”)
去
将IDENTITY_INSERT[dbo].[Roles]设置为OFF
去
用于通过存储过程将值从一个表插入到另一个表。我用了和,后者几乎和安多玛的答案一样
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
不是这样的
INSERT INTO tableA
SELECT * FROM tableB
SET IDENTITY_INSERT tableA OFF
有一个或多个c
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;
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);
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
SET IDENTITY_INSERT tableA ON
INSERT Into tableA ([id], [c2], [c3], [c4], [c5] )
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB
INSERT INTO tableA
SELECT * FROM tableB
SET IDENTITY_INSERT tableA OFF