У меня есть сценарий, который вызывает хранимую процедуру на другом SQL сервере, используя ссылку на связанный сервер и инструкцию OPENQUERY()
. Для демонстрации я выполнил следующую процедуру на удаленном сервере:
-- ON SQL_SVR Remote Server
CREATE PROC [dbo].[MyProc]
( @Pram_A NVARCHAR(4) OUTPUT
,@Pram_B NVARCHAR(4) OUTPUT
,@Pram_C NVARCHAR(4) OUTPUT
,@Pram_D NVARCHAR(4) OUTPUT
)
AS
SELECT
@Pram_A = 'foo'
,@Pram_B = 'bar'
,@Pram_C = 'this'
,@Pram_D = 'that'
GO
Теперь я хотел бы вызвать эту процедуру и получить все четыре значения, которые она возвращает, поэтому я написал следующий сценарий на локальный сервер:
-- These variables are final resting places for my data
DECLARE
@Pram_1 NVARCHAR(4)
,@Pram_2 NVARCHAR(4)
,@Pram_3 NVARCHAR(4)
,@Pram_4 NVARCHAR(4);
DECLARE
@SQL NVARCHAR(MAX)
-- I will pass values from the remote proc to the dynamic sql through some output parameters, which are middle men between the remote Alpha and the local Numeric params
,@Parms NVARCHAR(MAX) = '@Pram_A1 NVARCHAR(4) OUTPUT, @Pram_B2 NVARCHAR(4) OUTPUT, @Pram_C3 NVARCHAR(4) OUTPUT, @Pram_D4 NVARCHAR(4) OUTPUT'
,@LinkedServer VARCHAR(50) = '[SQL_SVR]';
-- The dynamic sql expects to get the middle-men parameters, which it will fill with the values it gets for it's alpha-style params
SET @SQL = 'SELECT * FROM OPENQUERY(' + @LinkedServer + ',''EXEC [dbo].[MyProc] @Pram_A = @Pram_A1 OUTPUT, @Pram_B = @Pram_B2,@Pram_C = @Pram_C3,@Pram_D = @Pram_D4'')';
-- Take whatever the remote proc puts into the middle-men params and put it into our local numeric params
EXEC sp_executesql @SQL, @Parms
,@Pram_A1 = @Pram_1 OUTPUT
,@Pram_B2 = @Pram_2 OUTPUT
,@Pram_C3 = @Pram_3 OUTPUT
,@Pram_D4 = @Pram_4 OUTPUT;
-- show the contents of the local, numeric params.
SELECT
@Pram_1 AS P1
,@Pram_2 AS P2
,@Pram_3 AS P3
,@Pram_4 AS P4;
Насколько мне известно, все это правильное использование (довольно сложного) передачи параметров, объявления локальных параметров и передачи их динамику c sql и внутри динамического c sql, используя те, которые объявлены в удаленном скрипте. Однако, когда я запускаю вышеуказанное, я получаю следующее предупреждение и ошибку:
--OLE DB provider "SQLNCLI11" for linked server "PRODSQL-V2" returned message "Deferred prepare could not be completed.".
'Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@Pram_A1".'
Я тщательно искал решение, но все, на что я смотрю, похоже, подразумевает, что мой сценарий правильный. Я знаю, что, должно быть, что-то неправильно понял и совершил ошибку, но я не могу понять, что именно! Можете ли вы увидеть, что я сделал не так, или объяснить возможную причину сбоя сценария?
Примечание 1. Существуют причины для использования динамического c sql и переменного имени сервера, которые не показаны в очень упрощенный пример сценария.
Примечание 2: локальный сценарий находится на SQL сервере 14.0.3048.4, удаленный - на 13.0.4001.0