web-dev-qa-db-fra.com

SQL Server: Comment appeler une fonction définie par l'utilisateur (UDF) sur un serveur lié?

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é?

11
Ian Boyd

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'
3
PollusB

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 
1
Denis

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
1
Sheikh M. Haris
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
0
Amy A