Wybieranie danych z dwóch różnych serwerów w SQL Server


363

Jak mogę wybrać dane w tym samym zapytaniu z dwóch różnych baz danych, które znajdują się na dwóch różnych serwerach w SQL Server?


6
Odpowiedzi od Erica i Raging Bull są bardzo przydatne. Byłem w stanie to wykorzystać do skopiowania masowych ilości danych z DEV do PROD, skracając czasy od 5 godzin do 18 godzin, do 17 sekund.
Chris Aldrich

@Eric, podziękowania za edycję marginalnie dwuznacznego pytania i uczynienie go pytaniem o 170 powtórzeń :)
Eric Wu

Odpowiedzi:


345

To, czego szukasz, to połączone serwery. Możesz się do nich dostać w SSMS z następującej lokalizacji w drzewie Eksploratora obiektów:

Server Objects-->Linked Servers

lub możesz użyć sp_addlinkedserver .

Musisz tylko skonfigurować jeden. Gdy to zrobisz, możesz wywołać tabelę na innym serwerze w następujący sposób:

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

Pamiętaj, że właściciel nie zawsze jest dbotaki, więc pamiętaj, aby zastąpić go dowolnym używanym schematem.


13
czy możemy to zrobić bez połączonych serwerów?
Steam

5
@Eric, gdzie są obiekty serwerowe w SSMS?
Tsahi Asher,

9
@TsahiAsher - Podczas łączenia się z serwerem Server Objects jest folderem w drzewie Eksploratora obiektów.
Eric

2
Jeśli nie jest znany, można również pominąć schemat, aby użyć domyślnego. Np [OtherServerName].[OtherDB]..[OtherTable]. Najlepiej jednak dołączyć, jeśli jest znany.
Tom Bowers

92

Możesz to zrobić za pomocą Połączonego serwera.

Zwykle połączone serwery są skonfigurowane tak, aby umożliwić aparatowi bazy danych wykonanie instrukcji Transact-SQL, która zawiera tabele w innej instancji SQL Server lub innym produkcie bazodanowym, takim jak Oracle. Wiele typów źródeł danych OLE DB można skonfigurować jako połączone serwery, w tym Microsoft Access i Excel.

Połączone serwery oferują następujące zalety:

  • Możliwość dostępu do danych spoza SQL Server.
  • Możliwość wydawania rozproszonych zapytań, aktualizacji, poleceń i transakcji na heterogenicznych źródłach danych w całym przedsiębiorstwie.
  • Możliwość podobnego adresowania różnych źródeł danych.

Przeczytaj więcej o połączonych serwerach .

Wykonaj następujące kroki, aby utworzyć serwer połączony:

  1. Obiekty serwera -> Połączone serwery -> Nowy połączony serwer

  2. Podaj nazwę zdalnego serwera.

  3. Wybierz typ zdalnego serwera (SQL Server lub inny).

  4. Wybierz Bezpieczeństwo -> Wykonaj przy użyciu tego kontekstu bezpieczeństwa i podaj login i hasło do zdalnego serwera.

  5. Kliknij OK i gotowe!

Oto prosty samouczek dotyczący tworzenia połączonego serwera.

LUB

Możesz dodać połączony serwer za pomocą zapytania.

Składnia:

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

Przeczytaj więcej o sp_addlinkedserver .

Połączony serwer musisz utworzyć tylko raz . Po utworzeniu połączonego serwera możemy wykonać kwerendę w następujący sposób:

select * from LinkedServerName.DatabaseName.OwnerName.TableName

Uwaga: patrz tutaj, aby nazwa serwera nie była nazwą hosta / portem.
Richard

1
Trochę napiwku, tutaj, jeśli masz problemy ze sp_addlinkedserver. Utwórz serwer w oknie dialogowym - upewnij się, że działa - następnie kliknij połączenie prawym przyciskiem myszy i wybierz scrip [t połączony serwer, jak tworzysz
Richard Housham

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

Możesz także spojrzeć na korzystanie z połączonych serwerów. Połączone serwery mogą być również innego rodzaju źródłami danych, takimi jak platformy DB2. Jest to jedna metoda próby uzyskania dostępu do bazy danych DB2 z wywołania SQL Server TSQL lub Sproc ...


2
czy ta metoda będzie działać przez cały czas? jakie są scenariusze, w których może się nie powieść?
Steam

3
Potwierdzono, że to kończy się niepowodzeniem w mojej env, błąd mówi, że potrzebowałem użyć addlinkedserver
gorlaz

1
Czy to działa dla każdego, bez korzystania z serwera połączonego?
Doug S

przetestowano i otrzymano błądCould 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

Zapytanie w 2 różnych bazach danych jest zapytaniem rozproszonym. Oto lista niektórych technik oraz plusy i minusy:

  1. Połączone serwery: zapewniają dostęp do szerszej gamy źródeł danych niż zapewnia replikacja programu SQL Server
  2. Połączone serwery: łącz się ze źródłami danych, których replikacja nie obsługuje lub które wymagają dostępu ad hoc
  3. Połączone serwery: działają lepiej niż OPENDATASOURCE lub OPENROWSET
  4. Funkcje OPENDATASOURCE i OPENROWSET : Wygodne w pobieraniu danych ze źródeł danych na zasadzie ad hoc. OPENROWSET ma również funkcje BULK, które mogą / nie mogą wymagać pliku formatu, który może być skrzypkiem
  5. OPENQUERY : Nie obsługuje zmiennych
  6. Wszystkie są rozwiązaniami T-SQL. Stosunkowo łatwe do wdrożenia i ustawienia
  7. Wszystkie są zależne od połączenia między źródłem a miejscem docelowym, co może mieć wpływ na wydajność i skalowalność

OPENQUERY nadal wymaga połączonego serwera, na którym nie działa OPENDATASOURCE
CJ

16

Spróbuj tego:

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

To są dobre odpowiedzi, ale tej brakuje i ma ona swoje potężne zastosowania. Być może nie pasuje do tego, czego chciał PO, ale pytanie było niejasne i czuję, że inni mogą tu znaleźć drogę. Zasadniczo możesz użyć 1 okna do jednoczesnego uruchomienia zapytania do wielu serwerów, oto jak:

W SSMS otwórz Zarejestrowane serwery i utwórz nową grupę serwerów w Lokalne grupy serwerów .

W ramach tej grupy utwórz rejestrację nowego serwera dla każdego serwera, do którego chcesz wysłać zapytanie. Jeśli nazwy DB są różne, ustaw wartość domyślną dla każdej właściwości.

Teraz wróć do grupy utworzonej w pierwszym kroku, kliknij prawym przyciskiem myszy i wybierz Nowe zapytanie. Otworzy się nowe okno zapytania, a każde uruchomione zapytanie zostanie wykonane na każdym serwerze w grupie. Wyniki są prezentowane w jednym zestawie danych z dodatkową nazwą kolumny wskazującą, z którego serwera pochodzi rekord. Jeśli użyjesz paska stanu, zauważysz, że nazwa serwera została zastąpiona wielokrotnością .


2
Wydaje się, że zakłada się, że zapytanie używa tych samych tabel we wszystkich bazach danych. (Co jest dobre w przypadku standardowych tabel, takich jak sys.tables, ale mało prawdopodobne w przypadku niestandardowych tabel, takich jak dbo.mycustomers)
Dennis Jaheruddin

Biorąc pod uwagę, że jest to „to samo zapytanie z dwóch różnych baz danych”, najprawdopodobniej mają te same tabele. Ale tak rutynowo używam tej metody do systemu produkcyjnego umieszczonego na kilku serwerach i do przeszukiwania tabel MSDB.
Paul

Naprawdę fajna funkcja. Wadą jest to, że schemat zestawu wyników musi być zgodny, ponieważ wykonuje zapytanie dwukrotnie i łączy je wszystkie jednocześnie. Byłoby wspaniale, gdybyś mógł odwoływać się do serwerów w samym SQL, tak jak możesz to zrobić z połączonymi serwerami, nawet jeśli nie mógłbyś ŁĄCZYĆ zestawu wyników, a zestawy musiały być zbudowane tak, aby były oceniane osobno.
Kross

1
@Kross możesz. Utwórz # tabelę wyników, zrób logikę na podstawie @@ SERVERNAME i zapełnij dane w #output, a następnie zakończ je zaznaczeniem. Zrobiłem podobnie, jeśli chodzi o wyszukiwanie informacji w dzienniku z mieszanki maszyn SQL2000 i SQL2008R2, które miały różne poziomy / kolumny informacji, ale zamiast @@ SERVERNAME używałem zmiennej wersji serwera.
Paul

9

Miałem ten sam problem z połączeniem SQL_server 2008 z SQL_server 2016 hostowanym na zdalnym serwerze. Inne odpowiedzi nie były dla mnie proste. Piszę tutaj moje poprawione rozwiązanie, ponieważ myślę, że może być przydatne dla kogoś innego.

Rozszerzona odpowiedź dla zdalnych połączeń IP db:

Krok 1: połącz serwery

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'

...gdzie SRV_NAME jest wymyślona nazwa. Użyjemy go, aby odnieść się do zdalnego serwera z naszych zapytań. aaa.bbb.ccc.dddto adres IP zdalnego serwera hostującego twoją bazę danych SQLserver.

Krok 2: Uruchom swoje zapytania Na przykład:

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

...i to wszystko!

Szczegóły składni: sp_addlinkedserver i sp_addlinkedsrvlogin


4

Utworzono definicję serwera połączonego na jednym serwerze do drugiego (musisz to zrobić SA), a następnie po prostu odnieś się do nich za pomocą 4-częściowej nazwy (patrz BOL).


4

Serwer 2008:

Będąc w SSMS podłączonym do server1.DB1 i spróbuj:

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

jak zauważyli inni, jeśli to nie działa, to dlatego, że serwer nie jest połączony.

Dostaję błąd:

Nie można znaleźć serwera DB2 w sys.servers. Sprawdź, czy podano prawidłową nazwę serwera. Jeśli to konieczne, wykonaj procedurę przechowywaną sp_addlinkedserver, aby dodać serwer do sys.servers.

Aby dodać serwer:

odniesienie: Aby dodać serwer za pomocą sp_addlinkedserver Link: [1]: Aby dodać serwer za pomocą sp_addlinkedserver

Aby zobaczyć, co jest w twoim sys.servers, po prostu zapytaj:

SELECT * FROM [sys].[servers]

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

2

Jak @ Super9 powiedział o OPENDATASOURCE przy użyciu uwierzytelniania SQL Server z dostawcą danych SQLOLEDB . Właśnie zamieszczam tutaj fragment kodu dla jednej tabeli w bieżącej bazie danych serwera, w której działa kod, a drugiej na innym serwerze „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')

więc powinno pójść tak -

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

0

Wiem, że to stare pytanie, ale używam synonimów. Podobno zapytanie jest wykonywane na serwerze bazy danych A i szuka tabeli na serwerze bazy danych B, który nie istnieje na serwerze A. Dodaj następnie synonim w bazie danych, która wywołuje twoją tabelę z serwera B. Twoje zapytanie nie musi dołącz dowolne schematy lub różne nazwy baz danych, wystarczy wywołać nazwę tabeli jak zwykle i zadziała.

Nie ma potrzeby łączenia serwerów, ponieważ synonimy na powiedzmy są rodzajem łączenia.


1
Czym zatem jest „synonim” w tym kontekście?
Oskar Berggren,

Jest to obiekt bazy danych, który odnosi się do obiektu podstawowego w innej bazie danych. Więcej informacji tutaj: docs.microsoft.com/en-us/sql/relational-databases/synonimy/…
Niklas Henricson

Fajnie, nie wiedziałem o tej funkcji. Jednak oświadczasz również, że unikają potrzeby połączenia z serwerem, ale nie widzę, jak to zrobić. Same synonimy wydają się być po prostu synonimem i same w sobie nie zawierają żadnej szczególnej zdolności do zdalnego sterowania. W przykładzie B na docs.microsoft.com/en-us/sql/t-sql/statements/… tworzą serwer połączony przed odwołaniem się do niego z synonimu.
Oskar Berggren,

To prawda, założyłem, że bazy danych znajdują się w tym samym środowisku serwerowym. Oczywiście zawsze będziesz musiał połączyć bazy danych, jeśli są one od siebie oddalone. Nie ma innego sposobu na dostęp z relacją między bazą danych.
Niklas Henricson,

0

Obiekty serwera ---> serwer połączony ---> nowy serwer połączony

Na połączonym serwerze napisz nazwę serwera lub adres IP dla innego serwera i wybierz SQL Server W zabezpieczeniach wybierz (wybierz przy użyciu tego kontekstu bezpieczeństwa) Wpisz login i hasło dla innego serwera

Teraz podłączony, a następnie użyj

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

0

Uproszczone rozwiązanie do dodawania połączonych serwerów

Pierwszy serwer

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

Drugie logowanie

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

Wykonuj zapytania z łącza do lokalnej bazy danych

INSERT INTO Tbl (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM [ip,port\instancename].[linkedDBName].[linkedTblSchema].[linkedTblName]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.