Comment écrire du SQL portable qui fait référence à un serveur lié?

9

J'ai une procédure stockée qui fait référence à un serveur lié. À plusieurs endroits de la procédure, j'ai quelque chose comme ceci:

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

Cette procédure existe dans mon environnement de développement, mon environnement de test et mon environnement en direct.

Le problème est que chaque copie de la procédure est subtilement différente car les noms de serveur sont différents pour chaque environnement. Cela rend la gestion du déploiement des mises à jour de script difficile.

Existe-t-il un moyen de rendre la procédure portable afin que chaque environnement puisse en exécuter des versions identiques?

Sinon, puis-je faire quelque chose pour rendre le déploiement de scripts moins sujet aux erreurs / erreurs?

Docteur Jones
la source
3
La création d'une vue qui diffère sur chaque serveur est-elle une option? Vous pouvez définir la vue comme SELECT <fields> FROM <linked server>mais utiliser le même nom de vue sur tous les serveurs pour maintenir le code à jour
JNK
@JNK ce n'est pas une mauvaise idée, il y a cependant pas mal de tableaux, mais au moins les vues seraient plus simples à maintenir qu'une procédure stockée avec des références de serveur liées parsemées.
Docteur Jones
@jnk, vous devriez en faire une réponse.
HLGEM

Réponses:

14

Le nom de votre serveur lié ne doit pas nécessairement être le nom du serveur. Vous pouvez utiliser un nom générique.

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'

Configurez le serveur lié sur chaque environnement avec le même nom, mais dirigez-le vers des serveurs différents.

Eli
la source
0

J'aime l'idée d'utiliser un nom de serveur lié générique. Cependant, dans de nombreux environnements, cela peut ne pas être possible. Dans ce cas, vous pouvez utiliser SQl dynamique dans votre 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
la source
1
Je noterai que si je faisais cela dans la vraie vie, j'utiliserais un bloc try catch et ferait une erreur si @linkedservername était nul après l'instruction set pour vous avertir que cela a été exécuté sur le mauvais serveur.
HLGEM
1
Si vous avez adopté cette approche, je pense que j'envelopperais l'instruction CASE dans une fonction, donc si un serveur changeait, je n'aurais qu'à mettre à jour la fonction.
Eli
Bon point @Eli
HLGEM