Контекст DB_ID від подальшого стека викликів


11

Чи можливо в SQL Server отримати DB_IDвихід із контексту далі від стека викликів?

Моя мета - створити деякі зручні (і, правда, хакі) функції утиліти в базі даних розробників, що дозволяють легко і стисло отримувати повноцінні назви об'єктів, надаючи їх короткі або фрагментовані імена, а також видаляти об'єкти, використовуючи те саме коротке ім'я . Ці функції утиліти будуть в одній базі даних утиліт, але викликаються з інших баз даних на тому ж сервері.

Що я бачу з тестування:

  • ORIGINAL_DB_NAME()як задумано повертає все, що було в рядку з'єднання, а не поточний контекст (задано USE [dbname]).
  • При виклику функції DB_NAME()повертає ім'я бази даних, де ця функція визначена . Іншим способом сказати це є те, що контекст всередині функції або зберігається процедури - це база даних, в якій вона визначена

Я знаю, що двигун відстежує кожен контекст бази даних вгору та вниз стеком викликів (див. Нижче для підтвердження). То чи є доступ до цієї інформації?

Я хочу мати змогу знаходити та працювати з об’єктами в контексті бази даних абонента, навіть якщо виконуючий код не в одній базі даних. Наприклад:

use SomeDB
EXEC util.dbo.frobulate_table 'my_table'

Я знаю, що можу просто зробити

EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'

Але мені просто цікаво, чи можна запитувати стек викликів таким чином.

Оновлення / примітка

Я читав і завантажував код із блогу Габріеля МакАдамса . Це забезпечує запис ідентифікатора процедури виклику вгору та вниз стеком, але при цьому передбачається, що все знаходиться в одній базі даних.

Доведення, що SQL Server запам'ятовує контекст БД вгору і вниз стеком викликів

Приклад: На сервері розробок з базами даних TestDB1 та 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 друкує:

Before, DB_NAME inside dbo.ECHO_STACK : TestDB2
TestDB1.dbo.ECHO_DB_NAME returned     : TestDB1
After, DB_NAME inside dbo.ECHO_STACK  : TestDB2

Це було б можливо через розширені події, але лише як новинка. Не щось для серйозного виробництва. Навіть якщо ви знаєте ім'я бази даних, як би ви її використали? У вас все в динамічному sql з USE xyz;попереднім?
Мартін Сміт

Чесно кажучи, я не можу сказати, що у мене є вагомий випадок, чому це було б необхідно . Я знайшов , що це дуже цікаво , і якби я зробити це цифра подам її в двох зручних маленьких пуття я використовую у своїй пісочниці Dev базі даних: Один , який отримує повне ім'я об'єкта даного найкоротший впізнаваний фрагмент назви (наприклад, в мій перший приклад у запитанні), а інший, який вбиває об’єкти, використовуючи іншу функцію для отримання повного імені, а також використовує тип ідентифікованого об'єкта для генерації DROPзаяви.
Джошуа Хоніг

Питання @SQLKiwi оновлено відповідно. Дякую і за іншу відповідь. У мене вже є різноманітні функції CLR для маніпулювання струнами, тому це має бути природним наступним кроком для мене.
Джошуа Хоніг

Відповіді:


4

Ви не можете цього виконати за допомогою функцій у базі даних утиліт. Однак можна створити корисні процедури в головній базі даних, позначити їх як системні об'єкти та викликати їх з контексту будь-якої бази даних у вашій системі. Статтю з хорошим прикладом можна знайти в цьому місці .


Це нове, але трохи небезпечне. Легко втратити відстеження подібних конфігурацій сервера під час переміщення в різні середовища (наприклад, новий сервер або нова версія SQL Server).
Майор Райлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.