在链接服务器上使用Identity Insert

时间:2015-04-29 07:24:13

标签: sql-server azure azure-sql-database linked-server

我已经在SQL管理工作室中在我们的内部SQL框中创建了一个链接服务器对象,我可以按照以下语法插入其中:

insert into [Azure].[budget].dbo.Bill 

我想设置身份插入并尝试了以下内容:

SET IDENTITY_INSERT [Azure].[budget].dbo.Bill ON
insert into [Azure].[budget].dbo.Bill 

这会产生前缀太多的错误。为什么我可以在没有身份插入的情况下插入它,是否可以以任何其他方式执行此操作?

然后我将身份插入部分更改为SP,如下所示:

EXEC [Azure].[budget].dbo.sp_executesql N'SET IDENTITY_INSERT Bill ON'
insert into [Azure].[budget].dbo.Bill 

但我收到一条关于没有获得BillID字段许可的警告

2 个答案:

答案 0 :(得分:1)

您无法在链接服务器中直接使用SET IDENTITY INSERT。 您需要使用动态SQL SET IDENTITY_INSERT ON

sp_executesql N'SET IDENTITY_INSERT [Azure].[budgetenergy].dbo.Bill ON;insert into [Azure].[budget].dbo.Bill ....';

答案 1 :(得分:0)

您可以 INSERT 将一个标识值添加到标识列的表格中链接服务器上,并使用“SWITCH TO” “技巧。

如果您没有使用“SWITCH TO”技巧来添加和删除列上的标识,那么即使在大型表格上也非常快!

从概念上讲,您只需创建一个新的SCHEMA,就像您想要INSERT的表一样,不需要定义的标识。然后将表格切换到该SCHEMA并执行INSERT。然后切换回定义了标识的SCHEMA 以下示例已在AZURE的链接服务器上进行了测试。 使用“SWITCH TO”的所有注意事项(索引必须相同,删除并重新创建外键等)

要进行测试,您可以在链接的Azure SQL Server数据库上运行以下完整脚本。您需要使用[LINKED_SERVER_NAME][DATABASE_NAME]进行查找/替换,并替换为您的值。在非Azure数据库上,您可能需要在表创建中添加“ON PRIMARY”。

--Let's setup the example by creating a table with an IDENTITY column on the Linked Server
EXEC('
CREATE TABLE [DATABASE_NAME].[dbo].[Example_Table](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nchar](10) NULL
)
 '
) AT [LINKED_SERVER_NAME]

--INSERT some data into the table
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] ([Name]) VALUES ('Travis')
INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] ([Name]) VALUES ('Jay')

-- Looks good
SELECT * FROM [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table]

GO


-- Create a TABLE with an identical schema, without the identity defined
EXEC('
CREATE TABLE [DATABASE_NAME].[dbo].[Example_Table_temp](
    [ID] [int] NOT NULL,
    [Name] [nchar](10) NULL
)
 '
) AT [LINKED_SERVER_NAME]

--Now Use the "SWITCH TO" to move the data to the new table
EXEC('
 ALTER TABLE [DATABASE_NAME].[dbo].[Example_Table] SWITCH TO [DATABASE_NAME].[dbo].[Example_Table_temp]
  '
) AT [LINKED_SERVER_NAME]


--Drop the old table (It should now be empty, but you may want to verify that if you are unsure here)
EXEC('
 DROP TABLE [DATABASE_NAME].[dbo].[Example_Table]
 '
) AT [LINKED_SERVER_NAME] 

--Rename the new table back to the old table name
-- NOTE the lack of database and owner identifiers in the new name
-- NOTE the use of double single qoutes (ESCAPED single quotes)
EXEC('
  EXEC sp_rename ''[DATABASE_NAME].[dbo].Example_Table_temp'',''Example_Table''
   '
) AT [LINKED_SERVER_NAME] 


  -- Now do your IDENTITY INSERTs !!!!

 INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] (ID,[Name]) VALUES (888,'Travis')
 INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] (ID,[Name]) VALUES (999,'Jay')

 --Verify they got put in
SELECT * FROM [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] 


  --Now let's switch it back to our SCHEMA with an IDENTITY

  EXEC('
CREATE TABLE [DATABASE_NAME].[dbo].[Example_Table_temp](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nchar](10) NULL
)

 ALTER TABLE [DATABASE_NAME].[dbo].[Example_Table] SWITCH TO [DATABASE_NAME].[dbo].[Example_Table_temp]

 DROP TABLE [DATABASE_NAME].[dbo].[Example_Table]

  EXEC sp_rename ''[DATABASE_NAME].[dbo].Example_Table_temp'',''Example_Table''
     '
) AT [LINKED_SERVER_NAME] 

--Data is still there
 SELECT * FROM [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] 
 GO
 -- And note you can no longer INSERT the IDENTITY
 INSERT INTO [LINKED_SERVER_NAME].[DATABASE_NAME].[dbo].[Example_Table] (ID,[Name]) VALUES (45,'Travis')
GO