Запустить динамическую c SQL хранимую процедуру сервера со связанным сервером - PullRequest
0 голосов
/ 09 июля 2020

Это динамическая c хранимая процедура, которая передает базу данных, связанный сервер и состояние. При выполнении этой хранимой процедуры она запускает хранимую процедуру в базе данных на связанном сервере и возвращает результаты.

Рабочий код - здесь связанный сервер является абсолютным и не передается как переменная

EXECUTE MYPROC 'CA','MYDB'
CREATE PROCEDURE [dbo].[MYPROC]
(
    @state varchar(2),
    @DATABASE char(20)
)
AS
    DECLARE @SQL @VARCHAR(MAX)
 
    SELECT @SQL = 'use ' + @DATABASE + ';
    SELECT * FROM pubs.dbo.authors WHERE state = @state'

    EXEC MYLINKSERVER.master.dbo.sp_executesql
              @SQL, N'@state char(2)', @state

Не рабочий код: здесь связанный сервер передается через переменную.

Я получаю «Синтаксическую ошибку» на @LINKEDSERVER**.**master

EXECUTE MYPROC 'CA','MYDB','MYLINKSERVER'
CREATE PROCEDURE [dbo].[MYPROC]
(
    @state varchar(2),
    @DATABASE char(20),
    @LINKEDSERVER VARCHAR(20)
)
AS
    DECLARE @SQL @VARCHAR(MAX)

    SELECT @SQL = 'use ' + @DATABASE + ';
    SELECT * FROM pubs.dbo.authors WHERE state = @state'

    EXEC @LINKEDSERVER.master.dbo.sp_executesql
            @SQL, N'@state char(2)', @state

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Попробуйте это в своем SP:

DECLARE @SQL VARCHAR(MAX);
SET @SQL = FORMATMESSAGE ( 'SELECT * FROM [%s].[%s].[dbo].[authors] WHERE [state] = ''%s'';', @LINKEDSERVER, @DATABASE, @state );
EXEC ( @SQL );

Это создаст следующий оператор SQL, который будет выполняться на основе параметров вашего примера выше:

SELECT * FROM [MYLINKSERVER].[MYDB].[dbo].[authors] WHERE [state] = 'CA';

Я не убедитесь, какая версия сервера SQL у вас установлена, поэтому вы не сможете использовать FORMATMESSAGE, однако я уверен, что вы знакомы с объединением строк.

0 голосов
/ 09 июля 2020

Я предпочитаю использовать OPENQUERY, поскольку обычно намного быстрее , чем использование запроса из четырех частей. Поэтому вместо SELECT * FROM [MYLINKSERVER].[MYDB].[dbo].[authors] WHERE [state] = 'CA'; попробуйте следующее:

SELECT * FROM OPENQUERY([MYLINKSERVER], '
    SELECT * FROM [MYDB].[dbo].[authors] WHERE [state] = ''CA''
')

И ваша процедура будет примерно такой

CREATE PROCEDURE [dbo].[MYPROC]
(
    @state CHAR(2),
    @DATABASE VARCHAR(20),
    @LINKEDSERVER VARCHAR(20)
)
AS

DECLARE @SQL NVARCHAR(500)

SET @SQL = N'SELECT * FROM OPENQUERY(' + QUOTENAME(@LINKEDSERVER) + ', ''
    SELECT * FROM ' + QUOTENAME(@DATABASE) + '.dbo.authors WHERE state = ''''' + @state + '''''
'')'
EXEC SP_EXECUTESQL @SQL
--PRINT @SQL -- To see the final query to execute

Или вы можете использовать FORMATMESSAGE в качестве ответа, данного Critical Error .

SET @SQL = FORMATMESSAGE ('SELECT * FROM OPENQUERY([%s], ''
    SELECT * FROM [%s].[dbo].[authors] WHERE [state] = ''''%s'''''');', QUOTENAME(@LINKEDSERVER), QUOTENAME(@DATABASE), @state
);
EXEC (@SQL);

Используйте QUOTENAME, чтобы избежать инъекции SQL. Поскольку другой параметр ограничен char(2), я думаю, это должно быть безопасно.

...