Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 只有在使用列列表且identity_INSERT位于SQL Server上时,才能为表中的identity列指定显式值_Sql Server - Fatal编程技术网

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)
      属性设置为
      。在幕后,这将创建一个脚本来重新创建表并复制现有数据,因此,要做到这一点,您还需要取消设置
      工具
      /
      选项
      /
      设计器
      /
      表和数据库设计器
      /
      防止保存需要重新创建表的更改

    • 使用此答案中描述的解决方法之一:
    如果“存档”表是主表的精确副本,那么我建议您删除id是一个identiy列的事实。这样可以让你插入它们

    或者,您可以使用以下语句为表允许和不允许标识插入

    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