Sql server PostgreSQL中的标量函数(非表值函数)
我使用PostgreSQL作为SQL server的链接服务器。现在,我需要调用只返回一个整数(标量)的PostgreSQL函数,但SQL Server不允许使用远程表值函数,并说此查询是一个表值函数Sql server PostgreSQL中的标量函数(非表值函数),sql-server,postgresql,remote-server,linked-server,Sql Server,Postgresql,Remote Server,Linked Server,我使用PostgreSQL作为SQL server的链接服务器。现在,我需要调用只返回一个整数(标量)的PostgreSQL函数,但SQL Server不允许使用远程表值函数,并说此查询是一个表值函数 CREATE OR REPLACE FUNCTION public.getpointinfo( IN lng double precision, IN lat double precision) RETURNS integer AS $$ DECLARE result intege
CREATE OR REPLACE FUNCTION public.getpointinfo(
IN lng double precision,
IN lat double precision)
RETURNS integer
AS
$$
DECLARE result integer;
begin
result:= case when cwt.k like 'maxspeed' then cast(cwt.v as integer)
else getmaxspeed(s.highway)
end maxspeed
from snapPointToLine(ST_SetSRID(ST_MakePoint($1, $2), 4326)) s
join current_way_tags cwt
on s.id = cwt.way_id
where cwt.k in ('maxspeed', 'highway')
order by cwt.k desc
limit 1;
return result;
end
$$
LANGUAGE plpgsql VOLATILE;
如何修改此PostgreSQL查询以返回标量值,或将其用作SQLServer中的四部分名称函数
select objectid, s.data_source
from testData
outer apply
(
select maxspeed from MB24DB.MobTrack24DB.[public].getpointinfo(X, Y)
) s
openquery
不是一个选项。我以前也做过类似的事情。你可以使用三个基本技巧
第一个技巧:xp\u cmdshell
您可以从UDF调用xp\u cmdshell
。因此,诀窍是让xp_cmdshell
调用sqlcmd
(或osql
)将结果放入表中,然后您可以从表中选择它们。您可以使用自己的SPID为结果设置关键帧
use tempdb
go
create table Results(
scope varchar(20) primary key,
result integer
)
go
create function dbo.test(@x integer, @y integer)
returns integer
as
begin
declare @sql nvarchar(max)
declare @scope varchar(20) set @scope = 'dbo.test@' + cast(@@spid as varchar(36))
set @sql = 'delete tempdb.dbo.Results where spid = '+@scope + '; '
set @sql = 'insert tempdb.dbo.Results select '+@scope+', '+cast(@x as nvarchar(max))+' * '+cast(@y as nvarchar(max))+' as r; '
declare @cmd varchar(max)
set @cmd = 'sqlcmd -E -Q "' + @sql +'"'
set @cmd = 'CMD /S /C "' + @cmd + ' 2>&1"'
exec xp_cmdshell @sql, NO_OUTPUT
declare @r integer
select @r = result from tempdb.dbo.results where scope = @scope
return @r
end
或者,您也可以使用UDF中的xp\u cmdshell
对表变量执行insert/exec
,然后解析输出数据
declare @CMD nvarchar(max)
set @CMD = 'echo.Hello World!'
set @CMD = 'CMD /S/C "' + @cmd + ' 2>&1"'
declare @results table (ix int identity primary key, txt nvarchar(max)
declare @exitcode int
insert @results(txt)
exec @exitcode = xp_cmdshell @commandtext
-- You now have the results of your command.
第二个技巧:sp\u OACreate
您可以使用sp_OACreate从UDF创建。这意味着您可以创建一个ADO连接回您自己的数据库,并执行任意操作,包括将结果放在表中以供参考sp_OACreate
使用起来很麻烦,因此我将把详细信息留给文档
第三个技巧:SQLCLR
您可以使用CLR函数绕过所有这些限制,该函数可以直接连接到您的postgres数据库并执行任何您想要的操作。我以前也做过类似的事情。你可以使用三个基本技巧 第一个技巧:
xp\u cmdshell
您可以从UDF调用xp\u cmdshell
。因此,诀窍是让xp_cmdshell
调用sqlcmd
(或osql
)将结果放入表中,然后您可以从表中选择它们。您可以使用自己的SPID为结果设置关键帧
use tempdb
go
create table Results(
scope varchar(20) primary key,
result integer
)
go
create function dbo.test(@x integer, @y integer)
returns integer
as
begin
declare @sql nvarchar(max)
declare @scope varchar(20) set @scope = 'dbo.test@' + cast(@@spid as varchar(36))
set @sql = 'delete tempdb.dbo.Results where spid = '+@scope + '; '
set @sql = 'insert tempdb.dbo.Results select '+@scope+', '+cast(@x as nvarchar(max))+' * '+cast(@y as nvarchar(max))+' as r; '
declare @cmd varchar(max)
set @cmd = 'sqlcmd -E -Q "' + @sql +'"'
set @cmd = 'CMD /S /C "' + @cmd + ' 2>&1"'
exec xp_cmdshell @sql, NO_OUTPUT
declare @r integer
select @r = result from tempdb.dbo.results where scope = @scope
return @r
end
或者,您也可以使用UDF中的xp\u cmdshell
对表变量执行insert/exec
,然后解析输出数据
declare @CMD nvarchar(max)
set @CMD = 'echo.Hello World!'
set @CMD = 'CMD /S/C "' + @cmd + ' 2>&1"'
declare @results table (ix int identity primary key, txt nvarchar(max)
declare @exitcode int
insert @results(txt)
exec @exitcode = xp_cmdshell @commandtext
-- You now have the results of your command.
第二个技巧:sp\u OACreate
您可以使用sp_OACreate从UDF创建。这意味着您可以创建一个ADO连接回您自己的数据库,并执行任意操作,包括将结果放在表中以供参考sp_OACreate
使用起来很麻烦,因此我将把详细信息留给文档
第三个技巧:SQLCLR
您可以使用CLR函数绕过所有这些限制,该函数可以直接连接到您的postgres数据库并执行任何您想执行的操作。posted函数有一个明显的语法错误。不应在
from
子句中使用标量函数。由于您这样做,我猜SQL Server假定它是一个表值函数。由于它是一个标量函数,我认为首先不需要使用交叉应用。只需将MB24DB.MobTrack24DB.[public].getpointinfo(X,Y)
放入select
列表中(假设您的表testdata
有两列X和Y)@a_horse_,并抛出\u no_name错误:不允许远程函数引用'MB24DB.MobTrack24DB.public.getpointinfo',而列名“MB24DB”找不到或不明确。testData包含X和Y列。然后尝试外部应用(选择MB24DB.MobTrack24DB.[public].getpointinfo(X,Y)@a\u horse\u与\u no\u name相同错误。发布的函数有一个明显的语法错误。在from
子句中不应使用标量函数。由于您这样做,我猜SQL Server假定它是一个表值函数。由于它是一个标量函数,我认为首先不需要使用交叉应用必须将MB24DB.MobTrack24DB.[public].getpointinfo(X,Y)
放入select
列表中(假设您的表testdata
有两列X和Y)@引发了一个没有名称的错误:不允许远程函数引用“MB24DB.MobTrack24DB.public.getpointinfo”,并且列名“MB24DB”找不到或不明确。testData包含X和Y列。然后尝试外部应用(选择MB24DB.MobTrack24DB.[public].getpointinfo(X,Y)
@a_horse_with_no_name同一错误。Ben,正如我在评论中所说,它抛出一个错误:不允许远程函数引用'MB24DB.MobTrack24DB.public.getpointinfo',并且列名'MB24DB'找不到或不明确。我已经尝试了所有建议的。Ben,正如我在评论中所说,它抛出一个错误:远程函数引用'M'B24DB.MobTrack24DB.public.getpointinfo”是不允许的,并且列名“MB24DB”找不到或不明确。我已经尝试了所有建议。