Контекст 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 печатает:

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;предшествующим ему?
Мартин Смит
Честно говоря, я не могу сказать, что у меня есть веские аргументы в пользу того, почему это необходимо . Я нашел это очень интересным, и если я это выясню, я добавлю его в два удобных маленьких процесса, которые я использую в своей базе данных разработчика песочницы: тот, который получает полное имя объекта, учитывая самый короткий распознаваемый фрагмент имени (например, в мой первый пример в вопросе), и другой, который убивает объекты, используя другую функцию, чтобы получить полное имя, а также использует тип идентифицированного объекта для генерации DROPоператора.
Джошуа Хониг
@SQLKiwi Вопрос обновлен соответственно. Спасибо за другой ответ тоже. У меня уже есть множество функций CLR для работы со строками, так что это должно быть естественным следующим шагом для меня.
Джошуа Хониг

Ответы:

4

Вы не можете сделать это с помощью функций в базе данных утилит. Однако вы можете создавать служебные процедуры в базе данных master, отмечать их как системные объекты и вызывать их из контекста любой базы данных в вашей системе. Статью с хорошим примером можно найти по этому адресу .

nabrond
источник
Это роман, но немного опасно. При переходе в другие среды (например, на новый сервер или новую версию SQL Server) легко потерять отслеживание пользовательских конфигураций сервера.
Райли Майор,