PostgreSQL中的标量函数(NON表值函数)

时间:2016-02-01 10:04:17

标签: 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 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查询以返回标量值,或者能够将其用作SQL Server的四部分名称函数,如

select objectid, s.data_source
from testData
outer apply
(
select maxspeed from MB24DB.MobTrack24DB.[public].getpointinfo(X, Y)
) s

openquery不是一种选择。

1 个答案:

答案 0 :(得分:0)

我之前做过类似的事情。您可以使用三种基本技巧。

First Trick:xp_cmdshell

您可以从UDF中调用xp_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使用insert/exec对表变量执行xp_cmdshell ,然后解析输出数据。

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_OACreate

您可以使用UDF中的sp_OACreate。这意味着您可以创建一个ADO连接回到您自己的数据库并执行您希望的任意操作,包括将结果放在表中以供参考。 sp_OACreate使用起来很痛苦,所以我会留下您的文档以获取详细信息。

第三招:SQLCLR

您可以使用CLR函数解决所有这些限制,该函数可以直接连接到您的postgres数据库并执行您想要的任何操作。