Як написати портативний SQL, який відноситься до пов'язаного сервера?


9

У мене зберігається процедура, що стосується пов'язаного сервера. У кількох місцях протягом усієї процедури я отримав щось на зразок наступного:

INSERT INTO [TableName]
(...Columns...)
SELECT ...Columns...
FROM [ServerName\InstanceName].[Catalogue].[dbo].[TableName]
WHERE TableNameID = @TableNameID

Ця процедура існує в моєму середовищі розробки, тестовому середовищі та середовищі Live.

Проблема полягає в тому, що кожна копія процедури є тонко різною, оскільки імена серверів різні для кожного середовища. Це робить управління розгортанням оновлень скриптів клопітким.

Чи є спосіб зробити процедуру портативною, щоб кожне середовище могло виконувати однакові її версії?

Якщо ні, чи є щось, що я можу зробити, щоб розгортання сценарію було менш схильним до помилок / помилок?


3
Чи створюється подання, яке відрізняється на кожному сервері? Ви можете визначити перегляд як, SELECT <fields> FROM <linked server>але використовувати однакове ім'я перегляду на всіх серверах, щоб підтримувати код
JNK

@JNK, це не погана ідея, хоча існує досить багато таблиць, але принаймні представлення було б простішим у підтримці, ніж збережена процедура із пов’язаними посиланнями сервера, що пронизуються у всьому.
Доктор Джонс

@jnk, ти мусиш відповісти на це.
HLGEM

Відповіді:


14

Ім'я вашого пов’язаного сервера не повинно бути ім'ям сервера. Можна використовувати загальну назву.

EXEC master.dbo.sp_addlinkedserver
    @server = N'COMMONNAME',
    @srvproduct=N'MSDASQL',
    @provider=N'SQLNCLI',
    @provstr=N'DRIVER={SQL Server};SERVER=ACTUALSERVERNAME;UID=user1;PWD=rosebud567;', 
    @catalog=N'database1'

Налаштуйте зв'язаний сервер на кожному середовищі з тим же ім'ям, але насправді вкажіть їх на різних серверах.


0

Мені подобається ідея використання загального пов'язаного імені сервера. Однак у багатьох середовищах це може бути неможливим. У цьому випадку ви можете використовувати динамічний SQl у своєму sp.

declare @linkedservername nvarchar(200)
declare @sql nvarchar(4000)
SET @linkedservername =  CASE @@ServerName  
                            WHEN 'DevServer' THEN 'LinkedServerForDevEnvironment'
                            WHEN 'TestServer' THEN 'LinkedServerForTestEnvironment'
                            WHEN 'ProdServer' THEN 'LinkedServerForProdEnvironment'
                            ELSE Null
                        END   

set @sql = 'INSERT INTO [TableName] 
(...Columns...) 
SELECT ...Columns... 
FROM ' + @linkedservername + '.[Catalogue].[dbo].[TableName] 
WHERE TableNameID = @TableNameID'

Exec  @sql

1
Зауважу, що якби я робив це в реальному житті, я б використовував блок спробу лову і пускав помилку, якщо @linkedservername було нульовим після встановленого оператора, щоб попередити вас, що це було запущено на неправильному сервері.
HLGEM

1
Якщо ви скористалися цим підходом, я думаю, я би переклав операцію CASE у функцію, тож якщо сервер змінився, мені доведеться лише оновити функцію.
Елі

Гарна точка @Eli
HLGEM
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.