Wie kann ich Daten in derselben Abfrage aus zwei verschiedenen Datenbanken, die auf zwei verschiedenen Servern in SQL Server liegen, auswählen?
Antworten
Zu viele Anzeigen?Ich hoffe, dass die oben genannten Erläuterungen die ursprüngliche Frage des OP beantwortet haben. Ich möchte nur einen Code-Auszug hinzufügen, um SQL Server als Linked Server hinzuzufügen.
Im einfachsten Fall können wir SQL Server als Linked Server hinzufügen, indem wir sp_addlinkedserver
mit nur einem Parameter @server
ausführen, d. h.
-- Verwendung der IP-Adresse
exec sp_addlinkedserver @server='192.168.1.11'
-- PC-Domänenname
exec sp_addlinkedserver @server='DESKTOP-P5V8JTN'
SQL Server füllt automatisch SRV_PROVIDERNAME
, SRV_PRODUCT
, SRV_DATASOURCE
usw. mit Standardwerten. Durch das, müssen wir die IP oder den PC-Domänennamen in der 4-Teile-Tabellenadresse in der Abfrage angeben (Beispiel unten). Dies kann ärgerlicher oder weniger lesbar sein, wenn der Linked Server keinen Standardport oder keine Instanz hat, wird die Adresse ähnlich aussehen wie 192.168.1.11,1430
oder 192.168.1.11,1430\MSSQLSERVER2019
.
Um die 4-Teile-Adresse kurz und lesbar zu halten, können wir anstelle der vollständigen Adresse einen Aliasnamen für den Server hinzufügen, indem wir andere Parameter wie folgt angeben-
exec sp_addlinkedserver
@server='ReadSrv1',
@srvproduct='SQL Server',
@provider='SQLNCLI',
@datasrc='192.168.1.11,1430\MSSQLSERVER2019'
Aber wenn Sie die Abfrage ausführen, wird der folgende Fehler angezeigt- Es ist keine Angabe eines Anbieters oder irgendwelcher Eigenschaften für das Produkt 'SQL Server' möglich.
Wenn wir den Wert für die Server-Produkteigenschaft leer lassen ''
oder einen anderen Wert angeben, wird die Abfrage erfolgreich ausgeführt.
Nächster Schritt, melden Sie sich beim entfernten Linked Server an, indem Sie die folgende Abfrage ausführen-
EXEC sp_addlinkedsrvlogin @rmtsrvname = 'ReadSrv1', @useself = 'false', @locallogin = NULL, @rmtuser = 'sa', @rmtpassword = 'LinkedServerPasswordForSA'
Verwenden Sie schließlich den Linked Server mit 4-Teile-Adresse, die Syntax lautet-
[ServerName].[DatabaseName].[Schema].[ObjektName]
Beispiel-
SELECT TOP 100 t.* FROM ReadSrv1.AppDB.dbo.ExceptionLog t
- Um vorhandene Linked Server aufzulisten, führen Sie aus:
exec sp_linkedservers
- Um einen Linked Server zu löschen, führen Sie aus:
exec sp_dropserver @server = 'ReadSrv1', @droplogins='droplogins'
(löscht auch Anmeldungen) ODER
exec sp_dropserver @server = 'ReadSrv1', @droplogins='NULL'
(behalten Sie die Anmeldung)
Wie @Super9 über OPENDATASOURCE mit der Verwendung von SQL Server-Authentifizierung mit Datenanbieter SQLOLEDB berichtet hat. Ich poste hier nur einen Code-Schnipsel für eine Tabelle in der aktuellen Server-Datenbank, in der der Code ausgeführt wird, und eine andere auf einem anderen Server '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
Ich weiß, dass dies eine alte Frage ist, aber ich verwende Synonyme. Angeblich wird die Abfrage im Datenbankserver A ausgeführt und sucht nach einer Tabelle in einem Datenbankserver B, die auf Server A nicht existiert. Fügen Sie dann ein Synonym in der A-Datenbank hinzu, das Ihre Tabelle vom Server B aufruft. Ihre Abfrage muss keine Schemas oder verschiedene Datenbanknamen enthalten, rufen Sie einfach den Tabellennamen wie gewohnt auf, und es wird funktionieren.
Es ist nicht notwendig, Server als Synonyme zu verknüpfen, sie verknüpfen sozusagen.
Die meisten davon werden nicht funktionieren, wenn man versucht, CLR-Datentypen von einem Server auf einen anderen zu übertragen (d.h. GEOMETRY GEOGRAFIE - die nicht vereinigt oder eindeutig ausgewählt werden können, aber UNION ALL verwenden können). Kannst du OPENROWSET verwenden, um es zum Laufen zu bringen, aber es erfordert verknüpfte Server. Oder du kannst STAsText() verwenden, um den CLR-Typ in TEXT zu ändern, der auf die oben genannten Arten von Server zu Server weitergegeben werden kann.
Sie könnten auch ein verknüpftes Serverdatenkatalog erstellen. Abfragen Sie beide Server Sys. Tabellen mit voller äußerer Verknüpfungen und finden Sie Spaltennamen, die nur auf beiden Servern vorhanden sind. Tabellen und erstellen Sie dann dynamisch eine Spalte in dieser Ansicht, die "SELECT STRING_AGG(COMMON_COLUMNS) FROM Tabelle.Spalte" ist.
Dann könnten Sie von zentralen Verwaltungsservern aus eine Abfrage zu beliebiger Tabelle stellen, die unabhängig von Schemaänderungen auf beiden vorhanden ist. (Möglicherweise müssen Sie die Datentypen berücksichtigen, könnten aber immer einen CASE-Befehl in Ihrer Datenkatalogansicht verwenden, um jeden STA-Typ zu betrachten und in den niedrigstmöglichen Datentyp zu konvertieren, der für beide Spalten funktioniert.
Dann erstellen Sie ein Verfahren, das einen Parameter für @TABLE_NAME akzeptiert und die SQL-Spalte aus der von Ihnen erstellten Ansicht auswählt, wo der Tabellenname = @TABLE_NAME und führt es dynamisch aus. Sie sollten immer in der Lage sein, beliebige gemeinsame Tabellen abzufragen.
8 Stimmen
Die Antworten von Eric und Raging Bull waren sehr hilfreich. Ich konnte dies verwenden, um große Datenmengen von DEV nach PROD zu kopieren und die Zeiten von 5 Stunden bis 18 Stunden auf 17 Sekunden zu reduzieren.
0 Stimmen
@Eric, Lob für die Bearbeitung einer etwas mehrdeutigen Frage und daraus eine 170-Reputationsfrage zu machen :)