【SQL SERVER】OPENQUERY远程函数引用及参数传值问题
admin
2023-08-02 15:53:47
0

模拟数据

两台服务器,都安装有数据库,服务器A,服务器B。服务器B的数据库上配置有指向服务器A的数据库的链接数据库。服务器A的数据库Test里创建以下两个函数,一个函数返回一个表值,一个返回单个字符串值。

CREATE FUNCTION FUN_ReturnTable
(
    @para VARCHAR(50)
)
RETURNS @table TABLE(
    col VARCHAR(50)
)
AS
BEGIN
    INSERT INTO @table
            ( col )
    VALUES  ( \'This is Test.\'),
            ( @para )
RETURN
END 

GO 
CREATE FUNCTION FUN_ReturnValue (@para VARCHAR(50)) RETURNS varchar(50)
AS
BEGIN
        RETURN (\'Input para is \'+@para)
END 
GO

调用测试

服务器A上的数据库可以执行

SELECT * FROM  Test.dbo.FUN_ReturnTable(\'haha\') --返回表
SELECT dbo.FUN_ReturnValue(\'haha\') --返回单个值

然后在服务器B上的数据库运行以下语句调用(假设配置的链接服务器为LS)

SELECT LS.Test.dbo.FUN_ReturnValue(\'haha\')

于是就报错了:\”不允许远程函数引用 \’LS.Test.dbo.FUN_ReturnValue\’,找不到列名 \’LS\’,或者列名不明确。\”

解决方法

可以看到这样直接通过链接数据库调用是不行的。需要换个方式,改用OPENQUERY。

DECLARE @a VARCHAR(50)
set @a = (select * from openquery(LS,\'select Test.dbo.FUN_ReturnValue(\'\'haha\'\')\'))
select @a --返回的字符串值

SELECT * from openquery(LS,\'select * from Test.dbo.FUN_ReturnTable(\'\'haha\'\')\') --返回的表值

以上的调用,函数的参数值是写死的,如果传一个动态参数,改成下面这样:

DECLARE @a VARCHAR(50)
DECLARE @b VARCHAR(50)
set @a = (select * from openquery(LS,\'select Test.dbo.FUN_ReturnValue(\'\'\'+@b+\'\'\')\'))
select @a

是无法运行的,提示错误:


SQL-SERVER-RPC-FUNCTION-CALL-1

这个问题我就费解了,OPENQUERY的第二个参数不能直接带有动态变量,不知道啥原因,官网上也备注说明不可以含有参数。

解决方法是换种方式调用,改用EXEC的方法。

DECLARE @b VARCHAR(50)
DECLARE @sql varchar(500)
set @b = \'haha\';
set @sql = \'select a from openquery(LS,\'\'select Test.dbo.FUN_ReturnValue(\'\'\'\'\'+@b+\'\'\'\'\') AS a\'\')\';
exec(@sql);

以上语句是可以执行的,输出“Input para is haha”单行的字符串。那么现在问题来了,我想将现在输出的结果赋值给一个本地变量@a,所以想当然就这样写

DECLARE @a VARCHAR(50)
DECLARE @b VARCHAR(50)
DECLARE @sql varchar(500)
set @b = \'haha\';
set @sql = \'select a from openquery(LS,\'\'select Test.dbo.FUN_ReturnValue(\'\'\'\'\'+@b+\'\'\'\'\') AS a\'\')\';
set @a = exec(@sql); --是错误的,语法错误
set @a = (select * from exec(@sql)); --是错误的,语法错误
select @a;

以上给@a变量赋值方法都不行。于是将@a改为表变量。

DECLARE @b VARCHAR(50)
DECLARE @sql varchar(500)
DECLARE @a table( name varchar(50))
set @b = \'haha\';
set @sql = \'select a from openquery(LS,\'\'select Test.dbo.FUN_ReturnValue(\'\'\'\'\'+@b+\'\'\'\'\') AS a\'\')\';
insert into @a exec(@sql); --将结果插入表里
select name from @a

这样结果就保存到表变量了。调用返回表值的函数也是可以的。

DECLARE @b VARCHAR(50)
DECLARE @sql varchar(500)
DECLARE @a table( name varchar(50))
set @b = \'haha\';
set @sql = \'select * from openquery(LS,\'\'select * from Test.dbo.FUN_ReturnTable(\'\'\'\'\'+@b+\'\'\'\'\') AS a\'\')\'; --调用表值函数。
insert into @a exec(@sql);
select name from @a

总结

  • 1.SQL SERVER通过链接服务器是可以调用远程数据库的存储过程的。
    • 通过 exec LS.Test.dbo.testSP \'haha\' 的方式,其中LS是链接服务器,Test是数据库名称。但是这种方式需要将链接服务器配置为用户RPC。
    • 通过 select * from openquery(LS,\'exec Test.dbo.testSP \'\'haha\'\' \')的方式,其中LS是链接服务器,Test是数据库名称。
  • 2.SQL SERVER通过链接服务器远程调用函数不能通过 LS.Test.dbo.testFun(\'haha\')的方式直接调用,改用OPENQUERY的方式。
  • 3.OPENQUERY的第二个参数不能含有参数变量。如果需要传递参数,改成拼接字符串的形式,EXEC 命令执行字符串。

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python查找阿姆斯特朗数 题目解释 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数。 例如1^3 + 5...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...