Sélection de données à partir de deux serveurs différents dans SQL Server


363

Comment puis-je sélectionner des données dans la même requête à partir de deux bases de données différentes qui se trouvent sur deux serveurs différents dans SQL Server?


6
Les réponses d'Eric et Raging Bull sont très utiles. J'ai pu l'utiliser pour copier des volumes massifs de données de DEV vers PROD, réduisant ainsi les temps de 5 heures à 18 heures, jusqu'à 17 secondes.
Chris Aldrich

@Eric, bravo pour avoir édité une question légèrement ambiguë et en avoir fait une question à 170 reps :)
Eric Wu

Réponses:


345

Ce que vous recherchez, ce sont des serveurs liés. Vous pouvez y accéder dans SSMS à partir de l'emplacement suivant dans l'arborescence de l'Explorateur d'objets:

Server Objects-->Linked Servers

ou vous pouvez utiliser sp_addlinkedserver .

Il vous suffit d'en configurer un. Une fois que vous avez cela, vous pouvez appeler une table sur l'autre serveur comme ceci:

select
    *
from
    LocalTable,
    [OtherServerName].[OtherDB].[dbo].[OtherTable]

Notez que le propriétaire n'est pas toujours dbo, alors assurez-vous de le remplacer par le schéma que vous utilisez.


13
pouvons-nous le faire sans serveurs liés?
Steam

5
@Eric, où sont les objets serveur dans SSMS?
Tsahi Asher

9
@TsahiAsher - Lorsque vous vous connectez à un serveur, Server Objects est un dossier dans l'arborescence de l'explorateur d'objets.
Eric

2
S'il n'est pas connu, vous pouvez également omettre le schéma pour utiliser la valeur par défaut. Par exemple, [OtherServerName].[OtherDB]..[OtherTable]il est préférable de l'inclure s'il est connu.
Tom Bowers

92

Vous pouvez le faire en utilisant Linked Server.

Les serveurs généralement liés sont configurés pour permettre au moteur de base de données d'exécuter une instruction Transact-SQL qui inclut des tables dans une autre instance de SQL Server ou un autre produit de base de données tel qu'Oracle. De nombreux types de sources de données OLE DB peuvent être configurés en tant que serveurs liés, notamment Microsoft Access et Excel.

Les serveurs liés offrent les avantages suivants:

  • La possibilité d'accéder aux données depuis l'extérieur de SQL Server.
  • La possibilité d'émettre des requêtes distribuées, des mises à jour, des commandes et des transactions sur des sources de données hétérogènes à travers l'entreprise.
  • La capacité de traiter de manière similaire diverses sources de données.

En savoir plus sur les serveurs liés .

Suivez ces étapes pour créer un serveur lié:

  1. Objets serveur -> Serveurs liés -> Nouveau serveur lié

  2. Indiquez le nom du serveur distant.

  3. Sélectionnez le type de serveur distant (SQL Server ou autre).

  4. Sélectionnez Sécurité -> Soyez fait en utilisant ce contexte de sécurité et fournissez le login et mot de passe du serveur distant.

  5. Cliquez sur OK et vous avez terminé !!

Voici un didacticiel simple pour créer un serveur lié.

OU

Vous pouvez ajouter un serveur lié à l'aide d'une requête.

Syntaxe:

sp_addlinkedserver [ @server= ] 'server' [ , [ @srvproduct= ] 'product_name' ] 
     [ , [ @provider= ] 'provider_name' ]
     [ , [ @datasrc= ] 'data_source' ] 
     [ , [ @location= ] 'location' ] 
     [ , [ @provstr= ] 'provider_string' ] 
     [ , [ @catalog= ] 'catalog' ] 

En savoir plus sur sp_addlinkedserver .

Vous ne devez créer un serveur lié qu'une seule fois . Après avoir créé un serveur lié, nous pouvons l'interroger comme suit:

select * from LinkedServerName.DatabaseName.OwnerName.TableName

Remarque: voyez ici comment avoir un nom de serveur autre que le nom d'hôte / port.
Richard

1
Un petit conseil, ici si vous rencontrez des problèmes avec le sp_addlinkedserver. Créez le serveur dans la boîte de dialogue - assurez-vous que cela fonctionne - puis cliquez avec le bouton droit sur la connexion et sélectionnez le serveur lié script [AS AS create
Richard Housham

25
SELECT
        *
FROM
        [SERVER2NAME].[THEDB].[THEOWNER].[THETABLE]

Vous pouvez également envisager d'utiliser des serveurs liés. Les serveurs liés peuvent également être d'autres types de sources de données, telles que les plates-formes DB2. C'est une méthode pour essayer d'accéder à DB2 à partir d'un appel SQL Server TSQL ou Sproc ...


2
cette méthode fonctionnera-t-elle tout le temps? quels sont les scénarios où cela pourrait échouer?
Steam

3
Confirmé que cela échoue dans mon env, l'erreur indique que je devais utiliser addlinkedserver
gorlaz

1
Est-ce que cela fonctionne pour n'importe qui, sans utiliser de serveur lié?
Doug S

testé et erreur reçue estCould not find server '88.208.229.164' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
WhatsThePoint

22

L'interrogation sur 2 bases de données différentes est une requête distribuée. Voici une liste de quelques techniques ainsi que les avantages et les inconvénients:

  1. Serveurs liés: donne accès à une plus grande variété de sources de données que la réplication SQL Server
  2. Serveurs liés: connectez - vous avec des sources de données que la réplication ne prend pas en charge ou qui nécessitent un accès ad hoc
  3. Serveurs liés: performances supérieures à OPENDATASOURCE ou OPENROWSET
  4. Fonctions OPENDATASOURCE et OPENROWSET : pratique pour récupérer des données à partir de sources de données sur une base ad hoc. OPENROWSET a également des installations BULK qui peuvent / peuvent ne pas nécessiter un fichier de format qui pourrait être fiddley
  5. OPENQUERY : ne prend pas en charge les variables
  6. Ce sont toutes des solutions T-SQL. Relativement facile à mettre en œuvre et à configurer
  7. Tous dépendent de la connexion entre la source et la destionation, ce qui pourrait affecter les performances et l'évolutivité

OPENQUERY nécessite toujours un serveur lié, contrairement à OPENDATASOURCE
CJ

16

essaye ça:

SELECT * FROM OPENROWSET('SQLNCLI', 'Server=YOUR SERVER;Trusted_Connection=yes;','SELECT * FROM Table1') AS a
UNION
SELECT * FROM OPENROWSET('SQLNCLI', 'Server=ANOTHER SERVER;Trusted_Connection=yes;','SELECT * FROM Table1') AS a

16

Ce sont toutes de bonnes réponses, mais celle-ci manque et elle a ses propres utilisations puissantes. Peut-être que cela ne correspond pas à ce que voulait le PO, mais la question était vague et je pense que d'autres pourraient trouver leur chemin ici. Fondamentalement, vous pouvez utiliser 1 fenêtre pour exécuter simultanément une requête sur plusieurs serveurs, voici comment:

Dans SSMS, ouvrez Serveurs enregistrés et créez un nouveau groupe de serveurs sous Groupes de serveurs locaux .

Sous ce groupe, créez un nouvel enregistrement de serveur pour chaque serveur que vous souhaitez interroger. Si les noms de base de données sont différents, assurez-vous de définir une valeur par défaut pour chacun dans les propriétés.

Revenez maintenant au groupe que vous avez créé à la première étape, faites un clic droit et sélectionnez Nouvelle requête. Une nouvelle fenêtre de requête s'ouvrira et toute requête que vous exécuterez sera exécutée sur chaque serveur du groupe. Les résultats sont présentés dans un seul ensemble de données avec un nom de colonne supplémentaire indiquant de quel serveur provient l'enregistrement. Si vous utilisez la barre d'état, vous remarquerez que le nom du serveur est remplacé par plusieurs .


2
Cela semble supposer que la requête utilise les mêmes tables sur toutes les bases de données. (Ce qui est bien pour les tables standard comme sys.tables mais peu probable pour les tables sur mesure comme dbo.mycustomers)
Dennis Jaheruddin

Étant donné qu'il s'agit de "la même requête provenant de deux bases de données différentes", il est fort probable qu'il ait les mêmes tables. Mais oui, j'utilise régulièrement cette méthode pour un système de production hébergé sur plusieurs serveurs et pour interroger les tables MSDB.
Paul

Fonction vraiment cool en fait. L'inconvénient est que le schéma de l'ensemble de résultats doit correspondre, car il exécute la requête deux fois et les fusionne tous en même temps. Ce serait formidable si vous pouviez référencer les serveurs dans le SQL lui-même, comme vous le pouvez avec les serveurs liés, même si vous ne pouviez pas rejoindre l'ensemble de résultats et que les ensembles devaient être construits pour être évalués séparément.
Kross

1
@Kross vous pourriez en quelque sorte. Créez une table #output, faites une logique basée sur @@ SERVERNAME et remplissez les données dans #output, puis terminez-la avec une sélection. J'ai fait une chose similaire pour interroger les informations de journal à partir d'un mélange de machines SQL2000 et SQL2008R2 qui avaient différents niveaux / colonnes d'informations, mais au lieu de @@ SERVERNAME, j'utilisais une variable de version de serveur.
Paul

9

J'ai eu le même problème pour connecter un SQL_server 2008 à un SQL_server 2016 hébergé sur un serveur distant. D'autres réponses n'ont pas fonctionné directement pour moi. J'écris ma solution modifiée ici car je pense qu'elle peut être utile pour quelqu'un d'autre.

Une réponse étendue pour les connexions distantes IP db:

Étape 1: lier les serveurs

EXEC sp_addlinkedserver @server='SRV_NAME',
   @srvproduct=N'',
   @provider=N'SQLNCLI',   
   @datasrc=N'aaa.bbb.ccc.ddd';

EXEC sp_addlinkedsrvlogin 'SRV_NAME', 'false', NULL, 'your_remote_db_login_user', 'your_remote_db_login_password'

... où SRV_NAMEest un nom inventé. Nous l'utiliserons pour faire référence au serveur distant à partir de nos requêtes. aaa.bbb.ccc.dddest l'adresse IP du serveur distant hébergeant votre base de données SQLserver.

Étape 2: exécutez vos requêtes Par exemple:

SELECT * FROM [SRV_NAME].your_remote_db_name.dbo.your_table

...et c'est tout!

Détails de la syntaxe: sp_addlinkedserver et sp_addlinkedsrvlogin


4

Création d'une définition de serveur lié dans un serveur à l'autre (vous avez besoin de SA pour ce faire), puis référencez-les simplement avec un nom en 4 parties (voir BOL).


4

Server 2008:

Lorsque dans SSMS connecté à server1.DB1 et essayez:

SELECT  * FROM
[server2].[DB2].[dbo].[table1]

comme d'autres l'ont noté, si cela ne fonctionne pas, c'est parce que le serveur n'est pas lié.

Je reçois l'erreur:

Impossible de trouver le serveur DB2 dans sys.servers. Vérifiez que le nom de serveur correct a été spécifié. Si nécessaire, exécutez la procédure stockée sp_addlinkedserver pour ajouter le serveur à sys.servers.

Pour ajouter le serveur:

référence: pour ajouter un serveur à l'aide de sp_addlinkedserver Lien: [1]: pour ajouter un serveur à l'aide de sp_addlinkedserver

Pour voir ce qu'il y a dans vos serveurs sys., interrogez-le:

SELECT * FROM [sys].[servers]

3
 select * 
 from [ServerName(IP)].[DatabaseName].[dbo].[TableName]

2

Comme @ Super9 l'a expliqué sur OPENDATASOURCE à l'aide de l'authentification SQL Server avec le fournisseur de données SQLOLEDB . Je viens de publier ici un extrait de code pour une table se trouve dans la base de données de serveur actuelle où le code est en cours d'exécution et un autre sur un autre serveur '192.166.41.123'

SELECT top 2 * from dbo.tblHamdoonSoft  tbl1 inner JOIN  
OpenDataSource('SQLOLEDB','Data Source=192.166.41.123;User ID=sa;Password=hamdoonsoft')
.[TestDatabase].[dbo].[tblHamdoonSoft1] tbl2 on tbl1.id = tbl2.id

0
sp_addlinkedserver('servername')

donc ça devrait aller comme ça -

select * from table1
unionall
select * from [server1].[database].[dbo].[table1]

0

Je sais que c'est une vieille question mais j'utilise des synonymes. Soi-disant, la requête est exécutée dans le serveur de base de données A et recherche une table dans un serveur de base de données B qui n'existe pas sur le serveur A. Ajoutez ensuite un synonyme sur une base de données qui appelle votre table depuis le serveur B. Votre requête n'a pas à inclure des schémas ou des noms de base de données différents, il suffit d'appeler le nom de la table par habitude et cela fonctionnera.

Il n'est pas nécessaire de lier les serveurs car les synonymes sont, en quelque sorte, des liens.


1
Maintenant, qu'est-ce qu'un "synonyme" dans ce contexte?
Oskar Berggren

Il s'agit d'un objet de base de données qui fait référence à un objet de base dans une autre base de données. Plus d'informations ici: docs.microsoft.com/en-us/sql/relational-databases/synonymous/…
Niklas

Cool, je ne connaissais pas cette fonctionnalité. Cependant, vous déclarez également qu'ils évitent d'avoir besoin d'un serveur lié, mais je ne vois pas comment. Les synonymes eux-mêmes ne semblent être que cela, un synonyme, et ne contiennent pas en eux-mêmes de capacité d'accès distant spécifique. Dans l'exemple B sur docs.microsoft.com/en-us/sql/t-sql/statements/… , ils créent un serveur lié avant de le référencer à partir d'un synonyme.
Oskar Berggren

Certes, j'ai supposé que les bases de données se trouvent dans le même environnement de serveur. Bien sûr, vous devrez toujours lier des bases de données si elles sont éloignées les unes des autres. Il n'y a pas d'autre moyen d'accéder avec une relation de base de données à base de données.
Niklas Henricson

0

Objets serveur ---> serveur lié ---> nouveau serveur lié

Dans le serveur lié, écrivez le nom du serveur ou l'adresse IP pour un autre serveur et choisissez SQL Server In Security sélectionnez (être fait en utilisant ce contexte de sécurité) Écrivez le login et le mot de passe pour l'autre serveur

Maintenant connecté puis utilisez

Select * from [server name or ip addresses ].databasename.dbo.tblname

0

Solution simplifiée pour ajouter des serveurs liés

Premier serveur

EXEC sp_addlinkedserver @server='ip,port\instancename'

Deuxième connexion

EXEC sp_addlinkedsrvlogin 'ip,port\instancename', 'false', NULL, 'remote_db_loginname', 'remote_db_pass'

Exécuter des requêtes de liées à la base de données locale

INSERT INTO Tbl (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM [ip,port\instancename].[linkedDBName].[linkedTblSchema].[linkedTblName]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.