Kontekst DB_ID z dalszego stosu wywołań

11

Czy w SQL Server możliwe jest uzyskanie DB_IDkontekstu 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 przez USE [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
Joshua Honig
źródło
Byłoby to możliwe dzięki rozszerzonym wydarzeniom, ale tak naprawdę tylko jako nowość. Nie jest to coś do poważnego użytku produkcyjnego. Nawet jeśli znasz nazwę bazy danych, jak byś jej używał? Masz wszystko w dynamicznym SQL z USE xyz;poprzedzającym go?
Martin Smith
Szczerze mówiąc, nie mogę powiedzieć, że mam solidne uzasadnienie, dlaczego byłoby to konieczne . Uważam to za bardzo interesujące i jeśli to wymyślę, umieszczę je w dwóch poręcznych procesorach, których używam w mojej bazie danych piaskownicy: takiej, która otrzymuje pełną nazwę obiektu, biorąc pod uwagę najkrótszy rozpoznawalny fragment nazwy (na przykład w mój pierwszy przykład w pytaniu), a drugi, który zabija obiekty za pomocą innej funkcji, aby uzyskać pełną nazwę, a także używa typu zidentyfikowanego obiektu do wygenerowania DROPinstrukcji.
Joshua Honig,
@SQLKiwi Pytanie odpowiednio zaktualizowane. Dziękuję również za drugą odpowiedź. Mam już wiele funkcji CLR do manipulacji ciągami, więc powinien to być dla mnie naturalny następny krok.
Joshua Honig

Odpowiedzi:

4

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 .

nabrond
źródło
To powieść, ale trochę niebezpieczna. Podczas migracji do różnych środowisk (np. Nowego serwera lub nowej wersji SQL Server) łatwo jest zapomnieć o niestandardowych konfiguracjach serwera.
Riley Major