j'essaie d'appeler une fonction définie par l'utilisateur (UDF) sur un serveur lié:
CREATE FUNCTION [dbo].[UserGroupMembershipNames](@UserGUID uniqueidentifier)
RETURNS VARCHAR(8000)
AS
BEGIN
RETURN ASILIVE.ReportManager.dbo.UserGroupMembershipNames(@UserGUID)
END
Cela ne fonctionne pas, comme indiqué dans PRB: Un appel de fonction défini par l'utilisateur dans une requête de serveur lié en quatre parties échoue avec le message d'erreur 170 . Ils donnent également une solution de contournement:
Par exemple, au lieu de la requête suivante
Select * from Linked_Server.northwind.dbo.square_value(10)
lancer une requête avec la fonction Openquery:
Select * from Openquery(Linked_Server,'select northwind.dbo.square_ value(10)')
Si la fonction définie par l'utilisateur accepte des paramètres variables ou scalaires, vous pouvez utiliser la procédure stockée sp_executesql pour éviter ce problème. Par exemple:
exec Linked_Server.northwind.dbo.sp_executesql N'SELECT northwind.dbo.square_value(@input)',N'@input int',@input=10
Comment pourrais-je appliquer cette solution de contournement à ma situation et à la situation de ce gars-là ?
En d'autres termes:
Comment appeler un fichier UDF sur un serveur lié?
Pour appeler des procédures distantes, vous devez activer RPC OUT sur votre serveur lié. Ouvrez les propriétés du serveur lié dans SSMS, puis cliquez sur "Option de serveur" et assurez-vous que RPC Out est True.
Et ... Votre lien a la solution à votre problème. Regardez la dernière option dans la zone de travail
"exec Linked_Server.northwind.dbo.sp_executesql N'SELECT northwind.dbo.square_value (@input) ', N' @ input int ', @ input = 10"
Voici un cas de test pour vous:
use master
go
EXEC master.dbo.sp_addlinkedserver @server = N'(LOCAL)', @srvproduct=N'SQL Server';
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'(LOCAL)',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL;
EXEC master.dbo.sp_serveroption @server=N'(LOCAL)', @optname=N'rpc out', @optvalue=N'true'
GO
Use Testing
GO
CREATE FUNCTION [dbo].[UserGroupMembershipNames](@UserGUID uniqueidentifier)
RETURNS VARCHAR(8000)
AS
BEGIN
RETURN 'hello'
END
GO
select dbo.[UserGroupMembershipNames]('4278E0BF-2F7A-4D60-A09C-95E517E21EBC')
GO
exec [(LOCAL)].Testing.dbo.sp_executesql
N'select dbo.UserGroupMembershipNames(@UserGUID)',N'@UserGUID uniqueidentifier'
,@UserGUID='4278E0BF-2F7A-4D60-A09C-95E517E21EBC'
Ce n'est pas la solution la plus jolie, mais cela fonctionne si vous pouvez contourner le fait de passer des paramètres à la fonction de serveur lié
CREATE FUNCTION fn_LocalFunction
(
@SomeParamOfLinkedFunction VARCHAR(100)
)
RETURNS TABLE
AS
RETURN
SELECT SomeField
FROM OPENQUERY([YOURSERVER], 'SELECT * FROM [SOMEDB].dbo.fn_SomeRemoteFunction(NULL)') tst
WHERE SomeCondition = @SomeParamOfLinkedFunction
Cochez ce lien, qui est mon blog :
http://developersmania.blogspot.com/2012/11/call-user-defined-function-on-linked.html
Les détails simples du lien ci-dessus est la fonction ci-dessous.
CREATE FUNCTION [dbo].Function_Name(@Parameter INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @Word sysname
EXEC LinkedServer.DatabaseName.dbo.sp_executesql
N'SELECT DatabaseName.dbo.Function_Name(@Parameter)' --dynamic sql query to execute
,N'@Parameter int' --parameter definitions
,@Parameter=@Word OUTPUT --assigning the caller procs local variable to the dynamic parameter
RETURN @Word
END
Try the following changes:
CREATE FUNCTION [dbo].[UserGroupMembershipNames](@UserGUID uniqueidentifier)
RETURNS VARCHAR(8000)
AS
BEGIN
declare @sql nvarchar(800)
declare @param nvarchar(20)
declare @innersql nvarchar(400)
set @param = convert(char(20, @UserGUID )
set @innersql = 'select ReportManager.dbo.UserGroupMembershipNames('+@param+')'
set @sql = 'select * from openquery(ASILIVE,'' '+ @innersql +' '' )'
RETURN exec sp_executesql @sql
END