在SQL Server存储过程中以编程方式将链接服务器引用替换为本地数据库引用?

rhfm7lfc  于 2023-02-15  发布在  SQL Server
关注(0)|答案(4)|浏览(187)

作为脚本化过程的一部分,我尝试 * 以编程方式 * 更新存储过程中对链接服务器的引用。

SELECT foo, bar
FROM [Server].[Database].dbo.[Table]

我想翻译成:

SELECT foo, bar
FROM [Database].dbo.[Table]

我想在跨多个数据库的"触发并忘记"脚本中完全以编程方式完成此操作。
我现在的想法是使用元数据查找对链接表的引用,再次从元数据读取每个sp的文本,调整每个sp的文本,然后将每个更新的文本块推入一个exec语句中,逐个重建它们。
我确实想知道这是否会是一个巨大的痛苦,但是,所以有没有人有更好的想法?我愿意使用powershell,如果这可以提供一个更好的解决方案。
先谢了!

2ul0zpep

2ul0zpep1#

希望我能理解这些问题,但我建议您使用以下两种方法之一,而不是删除或替换[Server]:

  • 选项1:不更改任何SP。而是更新链接服务器配置以指向其他数据库,甚至是本地计算机。
  • 备选方案二:不要更改任何SP。而是开始使用SQL Server别名。SQL Server别名通过CliConfig应用工具进行管理,并最终存储在注册表中。因此,可以手动或通过. reg脚本应用它们。基本上,SQL Server别名将对服务器进行解密(以及端口)。如果更新链接服务器配置以引用SQL Server别名而不是特定服务器,只要你愿意,你可以将你的过程指向不同的服务器(甚至是本地服务器)。

希望能有所帮助。

zengzsys

zengzsys2#

坦白说,你的方法是最简单的。今年早些时候我也遇到过类似的问题

  • 读取sys.sql模块
  • REPLACE链接服务器文本并CREATE -〉ALTER
  • 执行(@结果)
izj3ouym

izj3ouym3#

下面是一个脚本,用于查找引用SQL 2005示例上的链接服务器的所有过程/函数/视图-可能也很有用:

USE master
GO
SET NOCOUNT ON;

--------------------------------------------------------------------
-- Test linked server connections
--------------------------------------------------------------------
BEGIN TRY   DROP TABLE #Svrs;   END TRY BEGIN CATCH END CATCH;

CREATE TABLE #Svrs
(
    [Server]                nvarchar(max),
    [CanConnectAsDefault]   bit
);

DECLARE @ServerName nvarchar(max), @RetVal int;

DECLARE Svrs CURSOR FAST_FORWARD READ_ONLY
FOR
    SELECT  ServerName = S.name
    FROM    sys.servers S;

OPEN Svrs;
FETCH NEXT FROM Svrs INTO @ServerName;
WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        EXEC @RetVal = sys.sp_testlinkedserver @ServerName;
    END TRY
    BEGIN CATCH
        SET @RetVal = sign(@@error);
    END CATCH;

    INSERT INTO #Svrs 
    SELECT  @ServerName 
        ,   CASE WHEN @RetVal = 0 THEN 1 ELSE 0 END;

    FETCH NEXT FROM Svrs INTO @ServerName;
END;
CLOSE Svrs;
DEALLOCATE Svrs;

SELECT * FROM #Svrs
DROP TABLE #Svrs;
GO

--------------------------------------------------------------------
-- Report linked server references
--------------------------------------------------------------------
BEGIN TRY   DROP TABLE #Refs;   END TRY BEGIN CATCH END CATCH;

CREATE TABLE #Refs
(
    [Server]    nvarchar(max),
    [Database]  nvarchar(max),
    [Schema]    nvarchar(max),
    [Object]    nvarchar(max),
    [Type]      nvarchar(max)
);

DECLARE @DatabaseName nvarchar(max), @ServerName nvarchar(max), @SQL nvarchar(max);
DECLARE Refs CURSOR FAST_FORWARD READ_ONLY
FOR
    SELECT  DatabaseName = D.name 
        ,   ServerName = S.name
    --  ,   ServerProvider = S.provider
    --  ,   ServerSource = S.data_source
    FROM    sys.databases D 
            CROSS JOIN sys.servers S
    WHERE D.name NOT IN ('master', 'tempdb', 'model', 'msdb', 'ReportServer', 'ReportServerTempDB');

OPEN Refs;
FETCH NEXT FROM Refs INTO @DatabaseName, @ServerName;
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @SQL = 'USE [' + @DatabaseName + '];                
                INSERT INTO #Refs 
                SELECT DISTINCT ''' + @ServerName + ''', ''' + @DatabaseName + ''', S.[name], O.[name], O.type_desc 
                FROM    syscomments C
                        INNER JOIN sys.objects O ON C.id = O.[object_id]
                        LEFT JOIN sys.schemas S ON S.[schema_id] = O.[schema_id]
                WHERE   C.[TEXT] LIKE ''%[ ,~[( '''']' + @ServerName + '[ .,~])'''' ]%'' ESCAPE ''~'';'

    PRINT 'Looking for ' + @ServerName + ' refs in ' + @DatabaseName -- + ': ' + @SQL;

    EXEC sp_executesql @SQL;

    FETCH NEXT FROM Refs INTO @DatabaseName, @ServerName;
END
CLOSE Refs;
DEALLOCATE Refs;

SELECT * FROM #Refs
DROP TABLE #Refs;
GO

--------------------------------------------------------------------
SET NOCOUNT OFF;
GO
eimct9ow

eimct9ow4#

这对于生产环境来说不是一个好主意,但是如果您需要一个用于开发目的的环回链接服务器,this非常适合我:

EXEC sp_addlinkedserver @server = N'name_for_linked_server',
    @srvproduct = N' ',
    @provider = N'SQLNCLI', 
    @datasrc = N'name_of_my_sqlserver_instance', 
    @catalog = N'name_of_database'

相关问题