2010-03-03 1 views
6

Ich schreibe ein Skript, das um eine Reihe von Servern laufen soll und eine Reihe von Daten auswählen soll, einschließlich des lokalen Servers. Das SQL, das benötigt wird, um die benötigten Daten auszuwählen, ist ziemlich kompliziert, also schreibe ich eine Art Ad-hoc-Ansicht und benutze eine OPENQUERY-Anweisung, um die Daten zu bekommen, also schliesse ich mich endlos über eine Anweisung wie diese:Warum ist OPENQUERY auf einem lokalen Server schlecht?

exec('INSERT INTO tabl SELECT * FROM OPENQUERY(@Server, @AdHocView)') 

Allerdings habe ich gehört, dass die Verwendung von OPENQUERY auf dem lokalen Server ist verpönt. Könnte jemand näher erläutern, warum?

+0

Dies ist ein Verwaltungsskript, also mache ich mir keine Sorgen um Berechtigungen. Meine Frage ist, gibt es irgendwelche Bedenken, wenn das Skript eine Schleife über die Liste der Server und läuft auf seinen eigenen Server-Namen? Dies führt in der Regel zu einem Fehler, der Server ist nicht für den Datenzugriff konfiguriert. Dieser Fehler kann behoben werden. EXEC sp_serveroption 'LocalServer', 'DATA ACCESS', TRUE – Dlongnecker

+0

überprüfen [Verbindungsserver] (http://msdn.microsoft.com/de-de us/library/ms188279.aspx) – Andrey

Antwort

6
  • Obwohl die Abfrage mehrere Ergebnismengen zurückgeben kann, gibt OPENQUERY nur die erste zurück.
  • OPENQUERY akzeptiert keine Variablen für ihre Argumente.
  • OPENQUERY kann nicht zum Ausführen erweiterter gespeicherter Prozeduren auf einem Verbindungsserver verwendet werden. Eine erweiterte gespeicherte Prozedur kann jedoch auf einem Verbindungsserver unter Verwendung eines vierteiligen Namens ausgeführt werden.
  • Wenn die sp_addlinkedserver gespeicherte Prozedur in demselben Skript verwendet wird, die Anmeldeinformationen auf dem Remote-Server verwendet werden, in das Skript fest einprogrammiert, sichtbar für jeden, der eine Kopie hat

Referenz:

+0

Ich hatte zufällig Gelegenheit, 'OPENQUERY' neulich zu verwenden und erkannte, dass dein 4. Punkt falsch war; 'OPENQUERY' operiert auf einem verbundenen Server, so dass keine Anmeldeinformationen fest codiert sind. Vielleicht denken Sie an "OPENROWSET". – Aaronaught

+0

@Aaronaught: Wenn eine verknüpfte Serverinstanz existiert, warum sollte OPENQUERY überhaupt verwendet werden? Wenn die gespeicherte Prozedur "sp_addlinkedserver" innerhalb desselben Skripts verwendet wird, hat mein Punkt Vorteile. –

+1

Nun, da Sie gefragt haben, gibt es tatsächlich einen Grund, 'OPENQUERY' zu verwenden: Performance. Mit 'OPENQUERY' kann die Anfrage auf dem Remote-Server abgearbeitet werden, während bei der 4-teiligen Standard-Benennung alle Zeilen auf den lokalen Server kopiert werden müssen, was bei großen Datensätzen ziemlich schlecht ist. Natürlich muss dies gegen die anderen Kompromisse abgewogen werden, die Sie erwähnt haben. – Aaronaught

2

Zusätzlich zu dem, was @OMG Ponies gesagt hat, ist es einfach unnötig. Es gibt keinen Grund, Ad-hoc-Abfragen und verteilte Transaktions-Semantiken einzuführen, wenn Sie dies nicht müssen. Wenn Sie OPENQUERY verwenden, übernehmen Sie alle negativen Aspekte von dynamischem SQL, einschließlich weniger vorhersehbarer Pläne und der Unfähigkeit des Servers, Abhängigkeiten genau zu verfolgen.

OPENQUERY erfordert auch, dass der lokale Benutzer über Berechtigungen für den Zielserver verfügt. Dies ist wahrscheinlich nicht das, was Sie möchten, es sei denn, es handelt sich um ein Verwaltungsskript. Sie können nicht erwarten, dass jeder Benutzer einer Datenbank dieselben Berechtigungen für jede andere Datenbank hat.

2

Nur ein Follow-up.

OpenQuery ist gut, wenn Sie einige Rowsets aus gespeicherten Prozeduren vergleichen oder bearbeiten müssen.

zum Beispiel, wenn Sie die Ergebnisse von zwei Servern (Test und Rollout-Server) vergleichen, wenn Sie von SQL Server 2005 zu SQL Server 2008 migrieren zum Beispiel, dann können Sie die folgende Abfrage tun:

select * into test_table from OpenQuery(testServer, 'exec testdb.dbo.test_sp'); 
select * into rollout_table from OpenQuery(rolloutServer, 'exec testdb.dbo.test_sp'); 

select * from test_table 
except 
select * from rollout_table; 

select * from rollout_table 
except 
select * from test_table; 

um Diskrepanzen zu sehen.