运行 动态 SQL 带链接服务器的服务器存储过程

Run dynamic SQL Server stored procedure with linked server

这是一个动态存储过程,将传递数据库、链接服务器和状态。执行此存储过程时,它会在链接服务器上的数据库上运行存储过程并返回结果。

工作代码 - 这里的链接服务器是绝对的,没有作为变量传递

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

提前致谢

在你的 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,但是,我确定您'重新熟悉连接字符串。

与使用四部分查询相比,我更喜欢使用 OPENQUERY as it is usually much faster。所以不用 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);

使用避免SQL注入。由于另一个参数限制为char(2),我想它应该是安全的。