Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server PostgreSQL中的标量函数(非表值函数)_Sql Server_Postgresql_Remote Server_Linked Server - Fatal编程技术网

Sql server PostgreSQL中的标量函数(非表值函数)

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

我使用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查询以返回标量值,或将其用作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”找不到或不明确。我已经尝试了所有建议。