Quiero usar un procedimiento almacenado para copiar una tabla de mi base de datos de prueba a un servidor vinculado con la misma ID/Identidad pero no puedo hacer que funcione ... He configurado el IDENTITY_INSERT
al ON
pero todavía se queja de la columna de ID.La inserción de identidad en el servidor vinculado falla
Aquí está mi procedimiento:
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
Pero cuando ejecuto el SP que me da el siguiente error:
The OLE DB provider "SQLNCLI10" for linked server .... could not INSERT INTO table "[LINKEDSERVER].[ProductManager].[dbo].[UIData]" because of column "Id". The user did not have permission to write to the column.
Vinculados propiedades de servidor de RPC y RPC a cabo se establece en true. Espero que alguien me ayude aquí.
ACTUALIZACIÓN: decidí a tirar las cosas aparte, primero copiar los datos desde el servidor local al servidor vinculado en un TEMP_TABLE
donde no tengo que lidiar con IDENTITY
cuestiones.
Luego escribí un procedimiento almacenado en el servidor vinculado/remoto, ya que no estoy usando SELECT *
, pero especifico la lista de columnas. Lo más probable es que esto funcionará desde el servidor local en un SP también, pero no tienen el tiempo o interés para comprobar que funciona todavía ..
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
Gracias por su respuesta Lucero pero si creo un SP para activar la identidad de en el servidor remoto y lo llaman: set = ATsql ATsql + 'EXEC [37.230.100.75] .ProductManager.dbo.TEST2PROD_IdentityOn;' ¿Me sale el mismo error? Saludos, Mike –
@MikeDole, todo el código (configuración identidad-inserción, inserción de datos, configuración de inserción de identidad desactivada) tendría que estar en ese SP. P.ej. puede alimentar elementos individuales para insertarlos en el SP, o si desea realizar operaciones de configuración, debe pasar un TVP o hacer que el servidor vinculado use el servidor local como servidor vinculado). – Lucero
FYI. No funciona mágicamente envolviéndolo en sql dinámico. Aún obtiene este error: el nombre del objeto 'LINKED_SERVER.DestinationDatabase.dbo.DestinationTable' contiene más que el número máximo de prefijos. El máximo es 2. –