2016-02-01 3 views
0

Я использую PostgreSQL в качестве связанного сервера с SQL Server. Теперь мне нужно вызвать функцию PostgreSQL, которая возвращает ТОЛЬКО одно целое (скалярное), но SQL Server не разрешает удаленные табличные функции и говорит, что этот запрос является табличной функцией.Скалярная функция (функция, отличная от таблицы) в PostgreSQL

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 не вариант.

+0

Представленная функция имеет очевидную синтаксическую ошибку. –

+0

Скалярная функция не должна использоваться в предложении 'from'. И поскольку вы это делаете, я полагаю, что SQL Server предполагает, что это функция, ориентированная на таблицу. И поскольку это скалярная функция, я не вижу необходимости использовать «cross apply» в первую очередь. Просто поставьте 'MB24DB.MobTrack24DB. [Public] .getpointinfo (X, Y)' в список 'select' (если ваша таблица' testdata' имеет два столбца x и y) –

+0

@a_horse_with_no_name Ошибка брошена: Ссылка на удаленные функции ' MB24DB.MobTrack24DB.public.getpointinfo 'не разрешено, а имя столбца «MB24DB» не может быть найдено или является двусмысленным. testData содержит столбцы X и Y. – Aleksandar

ответ

0

Я уже делал подобные вещи раньше. Есть три основных трюка, которые вы можете использовать.

Первый Trick: xp_cmdshell

Вы можете позвонить xp_cmdshell из UDF. Таким образом, уловка состоит в том, чтобы 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 = '[email protected]' + cast(@@spid as varchar(36)) 
    set @sql = 'delete tempdb.dbo.Results where spid = '[email protected] + '; ' 
    set @sql = 'insert tempdb.dbo.Results select '[email protected]+', '+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 

В качестве альтернативы, вы можете также сделать insert/execк табличной переменной с xp_cmdshell из UDF, а затем анализировать выходные данные.

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. 

Второй Trick: sp_OACreate

Вы можете использовать sp_OACreate из UDF. Это означает, что вы можете создать подключение ADO к своей собственной базе данных и выполнить любые произвольные действия, в том числе размещение результатов в таблице для справки. sp_OACreate - это боль в использовании, поэтому я оставлю вас в документации для деталей.

Третий Trick: SQLCLR

Вы можете обойти все эти ограничения с помощью функции CLR, которая может подключаться непосредственно к базе данных Postgres и делать все, что вы хотите.

+0

Бен, как я уже сказал в комментариях, он выдает сообщение об ошибке: Ссылка на удаленные функции «MB24DB.MobTrack24DB.public.getpointinfo» не разрешена, а имя столбца «MB24DB» не может быть найдено или является двусмысленным. Я уже пробовал все предлагаемые. – Aleksandar

+0

Вы правы ... – Ben