Bewerten Sie in T-SQL
Ich habe eine gespeicherte Prozedur, die es erlaubt einen IN-parameter angeben, welche Datenbank zu verwenden. Dann benutze ich eine pre-beschlossen Tabelle in dieser Datenbank für eine Abfrage. Das problem das ich habe ist die Verkettung der Tabellenname, der name der Datenbank innerhalb meiner Fragen. Wenn T-SQL hatte eine bewerten-Funktion, die ich tun könnte etwas wie
eval(@dbname + 'MyTable')
Derzeit bin ich fest erstellen Sie einen string und dann mit exec()
zu laufen, dass string als Abfrage. Dies ist unordentlich und ich möchte lieber nicht haben, um eine Zeichenfolge erstellen. Gibt es eine Möglichkeit, die ich auswerten kann, eine variable oder string, damit ich etwas tun kann, wie die folgenden?
SELECT *
FROM eval(@dbname + 'MyTable')
Ich würde es gerne bewerten, so landet es erscheinen wie diese:
SELECT *
FROM myserver.mydatabase.dbo.MyTable
- d03boy - ich löschte mein Vorschlag, da ich vergaß, dass "Verwenden" kann nicht verwendet werden, die in einer gespeicherten Prozedur. Ich hätte es besser wissen müssen, denn ich lief in dieses einige Monate zurück. Sorry, wenn ich führte Sie hinunter den falschen Pfad.
- Ich wusste es nicht, konnte nicht verwendet werden, so hab ich das zumindest gelernt, dass viel 🙂
- d03boy - ich löschte meinen Dritten Vorschlag die Verwendung von OPENROWSET so kann man die Variablen in der Verbindungszeichenfolge oder der Abfrage. Mist.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Lesen... Der Fluch und Segen von Dynamischem SQL, helfen mir sehr, zu verstehen, wie lösen diese Art von Problemen.
Es gibt kein "ordentlicher" Weg, dies zu tun. Sie sparen Zeit, wenn Sie akzeptieren es und schaut auf etwas anderes.
EDIT: Aha! Über die OP ' s Kommentar, dass "Wir haben Sie zum laden von Daten in eine neue Datenbank jeden Monat oder sonst wird es zu groß.". Erstaunlich im Nachhinein, dass niemand bemerkte den schwachen Geruch von diesem problem.
SQL Server bietet nativen Mechanismen für den Umgang mit Tabellen erhalten Sie "zu groß" ist (insbesondere, Partitionierung), die Ihnen erlauben, um die Adresse der Tabelle als eine Einheit, während die Aufteilung der Tabelle in separaten Dateien im hintergrund, so dass Sie Ihre aktuellen problem zusammen.
Um es anders auszudrücken, dies ist ein problem für Ihre DB-administrator, nicht der DB-consumer. Wenn das passiert, werden Sie als gut, ich schlage vor, Sie schauen in partitionieren dieser Tabelle.
versuchen die sp_executesql-built-in-Funktion.
Man kann im Grunde bauen Sie Ihre SQL-string in Ihr proc, dann rufen Sie
Können Sie nicht angeben, eine dynamische Tabellennamen im SQL-Server.
Gibt es ein paar Optionen:
Du hast gesagt, dass Sie nicht wie 1, also lets go für die 2.
Erste Möglichkeit ist die Beschränkung der messyness eine Zeile:
Ich bin mir nicht sicher, ich mag diese, aber es kann die beste option sein. Auf diese Weise werden alle der Wählt wird die gleiche sein.
Können Sie diese umgestalten, um Eure Herzen Inhalte, aber es gibt eine Reihe von Nachteilen auf, einschließlich das synonym erstellt wird in einer Transaktion, so dass Sie nicht zwei
die Abfragen laufen auf dem gleichen
Zeit (da beide versuchen werden
erstellen temptablesyn). Je
auf der locking-Strategie, wird man
blockieren die anderen.
Synonyme sind permanent, also das ist, warum müssen Sie dies tun, in einer Transaktion.
Gibt es ein paar Optionen, aber Sie sind chaotischer als die Art und Weise, die Sie bereits tun. Ich schlage vor, Sie entweder:
(1) Stick mit dem aktuellen Ansatz
(2) Gehen Sie vor und einbetten der SQL im code, da Sie tun es trotzdem.
(3) Seien Sie besonders vorsichtig, um überprüfen Sie Ihre Eingabe zur Vermeidung von SQL-Injection.
Auch, Unordnung ist nicht das einzige problem mit dynamischen SQL. Beachten Sie folgende Punkte:
(1) Dynamisches SQL konterkariert die Fähigkeit des Servers, erstellen Sie eine wiederverwendbare Ausführung planen.
(2) Die ExecuteSQL-Befehl bricht die besitzkette. Das bedeutet, dass der code ausgeführt wird, im Kontext des Benutzers, der die gespeicherte Prozedur aufruft, die NICHT der Besitzer der Prozedur. Dies könnte Sie zwingen, sich zu öffnen-Sicherheit auf, was Tabelle wird die Anweisung ausgeführt, und erstellen Sie andere Sicherheitsprobleme.
Nur ein Gedanke, aber wenn Sie eine vordefinierte Liste dieser Datenbanken ist, dann können Sie eine einzelne Ansicht in der Datenbank, die Sie verbinden, sich Ihnen anzuschließen - so etwas wie:
Dann könnten Sie übergeben den Namen Ihrer Datenbank in der gespeicherten Prozedur, und benutzt es einfach als Parameter in der WHERE-Klausel. Wenn die Tabellen groß sind, könnten Sie erwägen Sie die Verwendung einer indizierten Sicht, indexiert auf das neue database_name Spalte (oder was auch immer Sie es nennen), und die Tische' primary key (ich gehe davon aus die Frage, der Tabellen-schemas sind die gleichen?).
Natürlich, wenn Sie Ihre Liste der Datenbank Häufig ändert, dann wird das immer problematisch - aber wenn Sie zum erstellen dieser Datenbanken sowieso, dann die Aufrechterhaltung dieser Ansicht zur gleichen Zeit sollte nicht zu viel von einem Aufwand!
Ich denke auch, dass Mark Brittingham hat die richtige Idee (hier:
http://stackoverflow.com/questions/688425/bewerten-in t-sql/718223#718223), die zur Ausgabe eines
use database
Befehl und schreibt die sp NICHT voll qualifizieren, der name der Tabelle. Als er merkt, das handeln wird auf die Tabellen in der Anmeldung die aktuelle Datenbank.Lassen Sie mich hinzufügen, ein paar mögliche Ausführungen:
Aus einem Kommentar von dem OP entnehme ich der Datenbank geändert wird, einmal im Monat, wenn es "zu groß". ("Wir haben Sie zum laden von Daten in eine neue Datenbank jeden Monat oder sonst wird es zu groß. – d03boy")
Benutzernamen haben eine Standard-Datenbank, mit sp_defaultdb (veraltet) oder die ALTER LOGIN -. Wenn jeden Monat Sie bewegen sich auf die neue Datenbank, und nicht brauchen, um ausführen die sp auf die älteren Kopien, ändern Sie einfach die login-Standard-db-monatlich, und wieder nicht voll qualifizieren, der name der Tabelle.
Die Datenbank zu benutzen, können Sie in der client-login:
sqlcmd -U login_id -P password -d db_name
, dann exec die sp von dort.Stellen Sie eine Verbindung zur Datenbank über den client Ihrer Wahl (command-line -, ODBC -, JDBC), dann Frage einen
use database
Befehl exec sp.Verwendung von Datenbank-bar;
exec sp_foo;
Nachdem die Datenbank eingerichtet wurde mit einer der oben genannten, haben Sie drei Möglichkeiten für die Ausführung der gespeicherten Prozedur:
Konnte man nur kopieren Sie die sp zusammen mit der Datenbank in die neue Datenbank. Solange der name der Tabelle ist NICHT voll qualifiziert, Sie werde den Betrieb auf der neuen Datenbank-Tabelle.
exec sp_foo;
Können Sie installieren die einzige kanonische Kopie der sp in seiner eigenen Datenbank, nennen es
procs
mit der tablename nicht voll qualifiziert, und rufen Sie dann seine fuly qualifizierte name:exec ausgelöst.dbo.sp_foo;
Könnte man in jeder einzelnen Datenbank, installieren Sie eine stub -
sp_foo
dass die Produzenten für den vollständig qualifizierten Namen des echten sp, und dann execsp_foo
ohne qualifizierenden es. Die stub aufgerufen wird, und ruft die eigentliche Prozedur inprocs
. (Leideruse database dbname
kann nicht ausgeführt werden, der innerhalb einer sp.)Dies ist jedoch geschehen, wenn die Datenbank geändert wird, die real sp erstellt werden sollte, mit der
WITH RECOMPILE
option, ansonsten werde es cache ein plan für die Ausführung der falschen Tabelle. Die stub natürlich nicht brauchen.Könnte man erstellen Sie eine SQL-CLR-tabellenwertfunktionen UDF, um den Zugriff auf die Tabellen. Sie haben sich zu binden, um das schema, da TV-UDFs nicht unterstützt dynamisches schema. (Mein Beispiel beinhaltet eine ID und eine Spalte Titel - ändern Sie die für Ihre Bedürfnisse)
Sobald Sie dies getan haben, sollten Sie in der Lage zu tun, die follow-Abfrage:
Können Sie ein mehrteiliger name, in string zu.
zurück die ID,den Titel Spalten aus dieser Tabelle.
Werden Sie wahrscheinlich benötigen, um SQL-CLR und schalten Sie die option TRUSTWORTHY:
Erstellen Sie eine C# - SQL-Projekt, fügen Sie eine neue UDF-Datei, fügen Sie diese in es. Project Eigenschaft, Datenbank, Genehmigung Ebene externe. Erstellen, bereitstellen. Gemacht werden kann, ohne VisualStudio. Lassen Sie mich wissen, wenn Sie das brauchen.
Kopien in eine Globale temporäre Tabelle, die Sie dann verwenden können, wie eine normale Tabelle
Wenn Sie eine einigermaßen überschaubare Anzahl von Datenbanken, kann es am besten verwenden Sie einen pre-definiert bedingte Anweisung wie:
...
generieren Sie mit diesem proc-als Teil der Erstellung der Datenbank-Skripts wenn Sie die änderung der Liste der verfügbaren Datenbanken Abfragen.
Dies verhindert Sicherheitsprobleme mit dynamischem sql. Sie können auch verbessern Sie die Leistung durch den Austausch der 'select' - Anweisungen mit gespeicherten Prozeduren auf jeden Datenbank - (1-Cache execution plan pro Abfrage).