Czy w SQL Server możliwe jest uzyskanie DB_ID
kontekstu z poziomu stosu wywołań?
Moim celem jest stworzenie w podręcznej bazie danych piaskownicy deweloperskiej kilku przydatnych (i wprawdzie zhackowanych) funkcji narzędziowych, które ułatwiają uzyskanie zwięzłych nazw obiektów o ich krótkich lub pofragmentowanych nazwach, a dodatkowo usuwają obiekty o tej samej krótkiej nazwie . Te funkcje narzędziowe byłyby w pojedynczej bazie danych narzędzi, ale wywoływane z innych baz danych na tym samym serwerze.
Z tego, co widzę po testowaniu:
ORIGINAL_DB_NAME()
zgodnie z przeznaczeniem zwraca wszystko, co było w ciągu połączenia, a nie bieżący kontekst (ustawiony przezUSE [dbname]
).- Po wywołaniu w funkcji
DB_NAME()
zwraca nazwę bazy danych, w której zdefiniowano tę funkcję . Innym sposobem na powiedzenie tego jest to, że kontekst wewnątrz funkcji lub procedury składowanej to kontekst bazy danych, w której jest zdefiniowany
Wiem, że silnik śledzi każdy kontekst bazy danych w górę iw dół stosu wywołań (dowód poniżej). Czy jest więc jakiś sposób na dostęp do tych informacji?
Chcę być w stanie znaleźć i operować na obiektach w kontekście bazy danych obiektu wywołującego, nawet jeśli wykonywany kod nie znajduje się w tej samej bazie danych. Na przykład:
use SomeDB
EXEC util.dbo.frobulate_table 'my_table'
Wiem, że mogę to zrobić
EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'
Ale jestem naprawdę ciekawy, czy można w ten sposób zapytać stos wywołań.
Aktualizacja / notatka
Przeczytałem i pobrałem kod z bloga Gabriela McAdamsa . Zapewnia to zapis identyfikatora procedury wywoływania w górę iw dół stosu, ale nadal zakłada się, że wszystko znajduje się w tej samej bazie danych.
Dowód, że SQL Server zapamiętuje kontekst wywołania DB w górę i w dół stosu
Przykład: na serwerze deweloperskim z bazami danych TestDB1 i 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
ECHO_STACK proc drukuje:
Before, DB_NAME inside dbo.ECHO_STACK : TestDB2
TestDB1.dbo.ECHO_DB_NAME returned : TestDB1
After, DB_NAME inside dbo.ECHO_STACK : TestDB2
źródło
USE xyz;
poprzedzającym go?DROP
instrukcji.Odpowiedzi:
Nie można tego zrobić za pomocą funkcji w bazie danych narzędzi. Można jednak tworzyć procedury narzędziowe w głównej bazie danych, oznaczać je jako obiekty systemowe i wywoływać je z kontekstu dowolnej bazy danych w systemie. Artykuł z dobrym przykładem można znaleźć w tej lokalizacji .
źródło