来自更远的调用堆栈的DB_ID上下文


11

在SQL Server中,是否可以DB_ID从较远的调用堆栈中从上下文中获取?

我的目标是在dev沙箱数据库中创建一些方便的工具(并且很容易被发现),使给定其短名称或零散名称的对象的标准名称变得简单明了,并使用相同的短名称删除对象。这些实用程序功能将在单个实用程序数据库中,但会从同一服务器上的其他数据库调用。

从测试中我可以看到:

  • 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'

但是我真的很好奇,是否可以通过这种方式查询调用堆栈。

更新/注释

我确实从Gabriel McAdams的博客中阅读并下载了代码。这提供了堆栈上上下的调用过程ID的记录,但仍假定所有内容都在同一数据库中。

证明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;内容?
马丁·史密斯

老实说,我不能说我有充分的理由证明为什么这是必要的。我发现它非常有趣,如果弄清楚,我会将其放在沙盒开发数据库中使用的两个方便的小proc中:一个给出对象的全名,给出该名称的最短可识别片段(例如in我在问题中的第一个示例),另一个通过使用另一个函数获取全名来杀死对象,并且还使用所标识对象的类型来生成DROP语句。
Joshua Honig

@SQLKiwi问题已相应更新。也感谢您的其他回答。我已经有许多用于字符串操作的CLR函数,因此这对我来说自然是下一步。
Joshua Honig

Answers:


4

您无法使用实用程序数据库中的功能来完成此操作。但是,您可以在master数据库中创建实用程序,将它们标记为系统对象,然后从系统上任何数据库的上下文中调用它们。在此位置可以找到带有良好示例的文章。


这很新颖,但是有点危险。当您迁移到不同的环境(例如新服务器或新版本的SQL Server)时,很容易忘记这样的自定义服务器配置。
莱利少校
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.