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

发布于 2024-07-26 18:27:20 字数 465 浏览 3 评论 0原文

作为脚本化过程的一部分,我试图以编程方式更新存储过程中对链接服务器的引用。 我们有几个这样的参考文献:-

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

我想将其翻译为:-

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

我想在跨多个数据库的“即发即忘”脚本中完全以编程方式执行此操作。

我现在的想法是使用元数据查找对链接表的引用,再次从元数据中读取每个 sp 的文本,调整每个 sp 的文本,然后将每个更新文本块推入 exec 语句中以逐个重建它们-一。

我确实想知道这是否会是一个巨大的痛苦,那么有人有更好的想法吗? 如果可以提供更好的解决方案,我愿意使用 powershell。

提前致谢!

As a part of a scripted procedure I'm trying to programmatically update references to linked servers in stored procs. We have several references like this:-

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

Which I would like to translate to:-

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

I would like to do this entirely programmatically in a 'fire and forget' script across several databases.

The idea I have right now is to use metadata to find references to linked tables, read the text of each sp from metadata again, adjust each sp's text, then shove each block of updated text into an exec statement to rebuild 'em one-by-one.

I do wonder whether this will be a humongous pain however, so does anybody have any better ideas? I am open to using powershell if that could provide a better solution.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

王权女流氓 2024-08-02 18:27:21

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

  • 阅读 sys.sql_modules
  • REPLACE the linked server text and CREATE -> 更改
  • 执行(@Result)

Your approach is the easiest, frankly. I had a similar issue earlier this year

  • Read sys.sql_modules
  • REPLACE the linked server text and CREATE -> ALTER
  • EXEC (@Result)
云裳 2024-08-02 18:27:21

下面是一个脚本,用于查找引用 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

Here's a script to find all procs/functions/views that reference linked servers on a SQL 2005 instance - might be useful too:

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
陌路终见情 2024-08-02 18:27:21

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

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' 

This is not going to be a good idea for a production environment, but if you need a loopback linked server for dev purposes this worked for me:

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' 
心病无药医 2024-08-02 18:27:20

希望我能理解这些问题,但我建议采用以下两种方法之一:

  • 选项 1:不要更改任何服务器, 而不是删除或替换 [服务器]
    SP。 相反,更新链接
    服务器配置指向一个
    不同的数据库,甚至是本地的
    框。

  • 选项 2:不要更改任何
    SP。 相反,开始使用 SQL Server
    别名。 SQL Server 别名是
    通过 CliConfig 实用程序管理和
    最终存储在
    注册表。 因此,它们可以应用
    手动或通过 .reg 脚本。
    基本上,SQL Server 别名
    破译服务器(以及
    端口)正在被引用。 如果
    您更新链接服务器
    引用 SQL 的配置
    服务器别名而不是特定的
    服务器,你可以点你的程序
    每当您时到不同的服务器(甚至本地服务器)
    想。

我希望它有帮助。

Hopefully I am understanding the questions, but rather than removing or replacing [Server], I suggest one of two approaches:

  • Option 1: Don't change any of the
    SPs. Instead, update the linked
    server configuration to point a
    different database, even the local
    box.

  • Option 2: Don't change any of the
    SPs. Instead, start using SQL Server
    Aliases. SQL Server Aliases are
    managed via the CliConfig utility and
    are ultimately stored in the
    registry. Thus, they can be applied
    manually or via .reg script.
    Basically, the SQL Server Alias
    deciphers the server (along with
    port) which is being referenced. If
    you update the link server
    configuration to reference the SQL
    Server Alias rather than a specific
    server, you can point your procedures
    to different server (even the local server) whenever you
    would like.

I hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文