我想使用存储过程将表从测试数据库复制到具有相同ID / Identity的链接服务器,但无法正常工作。.我将其设置为IDENTITY_INSERT,ON但它仍然抱怨ID列。
IDENTITY_INSERT
ON
这是我的程序:
CREATE PROCEDURE [dbo].[TEST2PROD_CopyUIDataSServer] AS Begin declare @sql nvarchar(max) -- First truncate target table set @sql = 'EXEC [LINKEDSERVER].tempdb.sys.sp_sqlexec' + char(39)+ 'TRUNCATE Table [ProductManager].dbo.[UIData]' + char(39)+ ';' ---- SET IDENTITY_INSERT ON set @sql = @sql + 'EXEC [LINKEDSERVER].tempdb.sys.sp_sqlexec' + char(39)+ 'SET IDENTITY_INSERT [ProductManager].[dbo].[UIData] ON' + char(39)+ ';' ---- INSERT UIDATA records from DB1 into linked server DB2 set @sql = @sql + 'WITH TestData as (SELECT * from ProductManager.dbo.UIData UID)' + NCHAR(13)+ 'INSERT INTO [LINKEDSERVER].[ProductManager].[dbo].[UIData]' + NCHAR(13) + 'select * from TestData;' print @sql exec (@sql) end
但是,当我执行SP时,会出现以下错误:
由于列“ Id”,用于链接服务器....的OLE DB提供程序“ SQLNCLI10”无法插入表“ [LINKEDSERVER]。[ProductManager]。[dbo]。[UIData]”。用户没有写该列的权限。
链接服务器属性RPC和RPC out设置为true。我希望有人可以在这里帮助我吗?
更新: 我决定拆开东西,首先我将数据从本地服务器复制到链接服务器,TEMP_TABLE而不必处理IDENTITY问题。
TEMP_TABLE
IDENTITY
然后,我在链接/远程服务器上编写了一个存储过程,因为我没有使用SELECT *而是指定列列表。很有可能这也可以从SP中的本地服务器工作,但是我没有时间或兴趣来检查它。
SELECT *
USE [ProductManager] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[TEST2PROD_CopyBaseTables] AS BEGIN DECLARE @DestTable VARCHAR(50) DECLARE @DestPath VARCHAR(50) DECLARE @SrceTable VARCHAR(255) declare @sql nvarchar(max) DECLARE @columnList varchar(max) DECLARE @err int Begin TRY declare @comma_delimited_list varchar(4000) --- FIRST TRY WITH ONE TABLE, EXTENDABLE... set @comma_delimited_list = 'UIData' declare @cursor cursor set @cursor = cursor static for select * from dbo.Split(@comma_delimited_list,',') a declare @naam varchar(50) open @cursor while 1=1 begin fetch next from @cursor into @DestTable if @@fetch_status <> 0 break --Create tablenames SET @SrceTable = '[ProductManager].[dbo].TEMP_' + @DestTable SET @DestPath = '[ProductManager].[dbo].'+ @DestTable print @srceTable; print @DestTable; --Truncate target table set @sql ='TRUNCATE TABLE '+ @DestPath + ';' --Insert statement needs column names set @columnList ='' SELECT @columnList = coalesce(@columnList + '[' + name + '],','') FROM sys.columns Where OBJECT_NAME(OBJECT_ID) = @DestTable if RIGHT(RTRIM(@columnList),1) = ',' begin SET @columnList = LEFT(@columnList, LEN(@columnList) - 1) end --Transfer data from source table 2 destination set @sql = @sql + ' SET IDENTITY_INSERT ' + @DestPath + ' ON;' + ' INSERT INTO ' + @DestPath + '(' + @columnList + ') SELECT ' + @columnList + ' FROM ' + @SrceTable print @sql; exec (@sql) end -- not strictly necessary w/ cursor variables since the will go out of scope like a normal var close @cursor deallocate @cursor End Try Begin Catch declare @ErrorMsg nvarchar(MAX); select @ErrorMsg = ERROR_MESSAGE(); SELECT @err = @@error IF @err <> 0 Return @err end Catch END
IDENTITY_INSERT不适用于链接服务器AFAIK,除非您执行包含SET IDENTITY_INSERT批处理中的动态SQL或在远程服务器上为您执行此操作的某些代码(例如,Stored Proc)。
SET IDENTITY_INSERT
该IDENTITY_INSERT是每个会话(参见MSDN),当您使用远程服务器,这将可能是在从通过执行的语句不同的会话[LINKEDSERVER].tempdb.sys.sp_sqlexec,这会导致你看到它的发生是要失败的。
[LINKEDSERVER].tempdb.sys.sp_sqlexec