В 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
источник
USE xyz;
предшествующим ему?DROP
оператора.Ответы:
Вы не можете сделать это с помощью функций в базе данных утилит. Однако вы можете создавать служебные процедуры в базе данных master, отмечать их как системные объекты и вызывать их из контекста любой базы данных в вашей системе. Статью с хорошим примером можно найти по этому адресу .
источник