Ist es in SQL Server möglich, das DB_ID
aus dem Kontext weiter oben im Aufrufstapel abzurufen?
Mein Ziel ist es, einige praktische (und zugegebenermaßen hackige) Dienstprogrammfunktionen in einer Entwickler-Sandbox-Datenbank zu erstellen, die es einfach und übersichtlich machen, die vollständig qualifizierten Namen von Objekten anhand ihrer kurzen oder fragmentierten Namen abzurufen und zusätzlich Objekte mit demselben Kurznamen zu löschen . Diese Dienstprogrammfunktionen befinden sich in einer einzelnen Dienstprogrammdatenbank, werden jedoch von anderen Datenbanken auf demselben Server aufgerufen.
Nach dem, was ich beim Testen sehen kann:
ORIGINAL_DB_NAME()
Wie beabsichtigt wird zurückgegeben, was auch immer in der Verbindungszeichenfolge enthalten war, nicht der aktuelle Kontext (festgelegt vonUSE [dbname]
).- Beim Aufruf einer Funktion wird
DB_NAME()
der Name der Datenbank zurückgegeben, in der diese Funktion definiert ist . Eine andere Möglichkeit, dies zu sagen, besteht darin, dass der Kontext innerhalb einer Funktion oder gespeicherten Prozedur der der Datenbank ist, in der sie definiert ist
Ich weiß, dass die Engine jeden Datenbankkontext auf und ab des Aufrufstapels verfolgt (Beweis siehe unten). Gibt es also eine Möglichkeit, auf diese Informationen zuzugreifen?
Ich möchte in der Lage sein, Objekte im Kontext der Datenbank des Aufrufers zu finden und zu bearbeiten, obwohl sich der ausführende Code nicht in derselben Datenbank befindet. Beispielsweise:
use SomeDB
EXEC util.dbo.frobulate_table 'my_table'
Ich weiß, ich kann es einfach tun
EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'
Aber ich bin nur sehr gespannt, ob es möglich ist, den Aufrufstapel auf diese Weise abzufragen.
Update / Hinweis
Ich habe den Code aus Gabriel McAdams 'Blog gelesen und heruntergeladen . Dies liefert eine Aufzeichnung der aufrufenden Prozedur-ID im Stapel, setzt jedoch voraus, dass sich alles in derselben Datenbank befindet.
Beweis Der SQL Server merkt sich den Auf- und Ab-Aufrufstapel des DB-Kontexts
Beispiel: Auf einem Entwicklungsserver mit den Datenbanken TestDB1 und TestDB2
use TestDB1
GO
CREATE FUNCTION dbo.ECHO_DB_NAME() RETURNS nvarchar(128) BEGIN RETURN DB_NAME() END
GO
use TestDB2
GO
CREATE PROCEDURE dbo.ECHO_STACK AS
BEGIN
DECLARE @name nvarchar(128)
SET @name = DB_NAME()
PRINT 'Before, DB_NAME inside dbo.ECHO_STACK : ' + @name
SET @name = TestDB1.dbo.ECHO_DB_NAME()
PRINT 'TestDB1.dbo.ECHO_DB_NAME returned : ' + @name
SET @name = DB_NAME()
PRINT 'After, DB_NAME inside dbo.ECHO_STACK : ' + @name
END
GO
use master
SELECT DB_NAME() -- Returns 'master'
EXEC TestDB2.dbo.ECHO_STACK
Der ECHO_STACK-Prozess druckt:
Before, DB_NAME inside dbo.ECHO_STACK : TestDB2
TestDB1.dbo.ECHO_DB_NAME returned : TestDB1
After, DB_NAME inside dbo.ECHO_STACK : TestDB2
quelle
USE xyz;
vorangestellten?DROP
Anweisung zu generieren .Antworten:
Sie können dies nicht mit Funktionen in einer Dienstprogrammdatenbank erreichen. Sie können jedoch Dienstprogrammprozeduren in der Masterdatenbank erstellen, sie als Systemobjekte markieren und sie aus dem Kontext einer beliebigen Datenbank auf Ihrem System aufrufen. Ein Artikel mit einem guten Beispiel finden Sie an dieser Stelle .
quelle