Программная замена ссылок на связанные серверы ссылками на локальные базы данных в хранимых процессах SQL Server? - PullRequest
0 голосов
/ 09 июля 2009

В рамках скриптовой процедуры я пытаюсь программно обновить ссылки на связанные серверы в хранимых процессах. У нас есть несколько ссылок, как это: -

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

Который я хотел бы перевести на: -

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

Я хотел бы сделать это полностью программно в сценарии «забей и забудь» для нескольких баз данных.

Идея, которая у меня есть сейчас, заключается в том, чтобы использовать метаданные для поиска ссылок на связанные таблицы, снова читать текст каждого sp из метаданных, корректировать текст каждого sp, а затем помещать каждый блок обновленного текста в оператор exec, чтобы восстановить один-на-один.

Мне действительно интересно, будет ли это огромной болью, поэтому у кого-нибудь есть идеи получше? Я открыт для использования powershell, если это может обеспечить лучшее решение.

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

Ответы [ 4 ]

1 голос
/ 29 ноября 2009

Это не будет хорошей идеей для производственной среды, но если вам нужен сервер с обратной связью для целей разработки , это сработало для меня:

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' 
1 голос
/ 09 июля 2009

Ваш подход самый простой, честно говоря. У меня была похожая проблема ранее в этом году

  • Чтение sys.sql_modules
  • ЗАМЕНИТЕ текст связанного сервера и СОЗДАЙТЕ -> ИЗМЕНИТЬ
  • EXEC (@Result)
1 голос
/ 11 августа 2009

Вот скрипт для поиска всех procs / functions / views, которые ссылаются на связанные серверы в экземпляре 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
1 голос
/ 09 июля 2009

Надеюсь, я понимаю вопросы, но вместо удаления или замены [Сервер] я предлагаю один из двух подходов:

  • Вариант 1: не меняйте SPs. Вместо этого обновите связанный Конфигурация сервера, чтобы указать другая база данных, даже местная коробка.

  • Вариант 2. Не изменяйте SPs. Вместо этого начните использовать SQL Server Псевдонимы. Псевдонимы SQL Server управляется с помощью утилиты CliConfig и в конечном итоге хранятся в реестр. Таким образом, они могут быть применены вручную или через .reg скрипт. В основном, псевдоним SQL Server расшифровывает сервер (вместе с порт), на который ссылаются. Если вы обновляете сервер ссылок Конфигурация для ссылки на SQL Псевдоним сервера, а не конкретный сервер, вы можете указать свои процедуры на другой сервер (даже локальный сервер) всякий раз, когда вы хотел бы.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...