Jak napisać przenośny SQL, który odnosi się do połączonego serwera?

9

Mam procedurę składowaną, która odnosi się do połączonego serwera. W kilku miejscach procedury mam coś takiego:

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

Ta procedura istnieje w moim środowisku programistycznym, środowisku testowym i środowisku Live.

Problem polega na tym, że każda kopia procedury jest nieco inna, ponieważ nazwy serwerów są różne dla każdego środowiska. Utrudnia to zarządzanie wdrażaniem aktualizacji skryptów.

Czy istnieje sposób na przeniesienie procedury, aby każde środowisko mogło uruchamiać identyczne wersje?

Jeśli nie, to czy mogę coś zrobić, aby wdrożenie skryptu było mniej podatne na błędy / błędy?

Doktorze Jones
źródło
3
Czy tworzenie widoku różniącego się na każdym serwerze jest opcją? Można zdefiniować widok jako, SELECT <fields> FROM <linked server>ale używać tej samej nazwy widoku na wszystkich serwerach, aby zachować kod
JNK
@JNK to niezły pomysł, istnieje jednak sporo tabel, ale przynajmniej widoki byłyby łatwiejsze w utrzymaniu niż procedura przechowywana z połączonymi odnośnikami do serwera.
Doktor Jones
@ jnk, powinieneś udzielić odpowiedzi.
HLGEM 10.10.12

Odpowiedzi:

14

Nazwa połączonego serwera nie musi być nazwą serwera. Możesz użyć nazwy ogólnej.

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'

Skonfiguruj połączony serwer w każdym środowisku o tej samej nazwie, ale w rzeczywistości skieruj go na inne serwery.

Eli
źródło
0

Podoba mi się pomysł używania ogólnej nazwy serwera połączonego. Jednak w wielu środowiskach może to nie być możliwe. W takim przypadku możesz użyć dynamicznego SQl w swoim 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
HLGEM
źródło
1
Zauważę, że gdybym to robił w prawdziwym życiu, użyłbym bloku try catch i wyskoczyłby błąd, jeśli @linkedservername miał wartość zerową po instrukcji set, aby ostrzec cię, że został on uruchomiony na niewłaściwym serwerze.
HLGEM 10.10.12
1
Jeśli przyjmiesz takie podejście, myślę, że zawinę instrukcję CASE w funkcję, więc jeśli zmieni się serwer, będę musiał tylko zaktualizować funkcję.
Eli,
Dobry punkt @Eli
HLGEM 10.10