【发布时间】:2019-07-26 22:34:11
【问题描述】:
我在一个 SQL Server 2008 R2 上有许多不同的数据库。为了论证起见,我们称它们为 DB_A、DB_B 和 DB_C。我被要求开发为存储在 DB_A 上的存储过程。此存储过程将用于删除和创建索引,并将有关索引的一些额外信息存储在 DB_A 上的表中。当从 DB_C 或 DB_C 调用此存储过程时,它将能够在调用数据库上删除和创建索引,但将有关索引的额外信息存储在 DB_A 的表中。
这就是我想做的事情:我希望存储过程能够获得调用数据库的名称,而不必请求数据库名称作为参数。
这是一个简单的例子:
USE [DB_A]
CREATE PROC sp_WhatDatabaseAmICallingFrom
AS
BEGIN
DECLARE @calling_db NVARCHAR(128)
SET @calling_db = DB_NAME()
PRINT 'calling database: ' + @calling_db
END
当我在 DB_A 中执行存储过程时...
EXEC sp_WhatDatabaseAmICallingFrom
...它返回:“调用数据库:DB_A”
当我在 DB_B 中执行存储过程时...
USE DB_B
GO
EXEC DB_A.dbo.sp_WhatDatabaseAmICallingFrom
...它返回:“调用数据库:DB_A”。
在阅读了各种 SQL Server 元数据函数之后,这正是它应该做的。但我想要更改代码,以便将 @calling_db 设置为调用数据库的名称,以便我的示例存储过程将打印:“calling database: DB_B”。
很遗憾,我找不到任何可以执行此操作的元数据函数。关于如何做到这一点的任何想法?
【问题讨论】:
-
非常有趣的问题。出于好奇,您是否有理由不希望调用 sproc 的进程提供 dbname 作为参数(除了必须支持参数并提供它)?如果没有直接的方法来做到这一点,一种想法是使参数可选 @CallingDB NVARCHAR(128) = NULL 并检查值是否为空。如果是这样,默认使用 DB_NAME()。当然,这意味着来自其他数据库的调用需要提供名称...
-
我不想使用参数的唯一真正原因是我认为必须有办法做到这一点,而且我讨厌在没有找到解决方案的情况下离开这样的挑战。
-
仅供参考,同样的问题是asked on the DBA site,尽管尚未得到解答。提出的建议是使用扩展事件、SQL CLR 或使用
CONTEXT_INFO维护您自己的调用堆栈。 -
不确定这是否有帮助。但是,如果您在存储过程名称前加上“sp_”并将其放入主数据库,则 db_name() 将返回调用存储过程的数据库名称。当您调用存储过程时,不要使用数据库名称(即 exec master.. sp_WhatDatabaseAmICallingFrom)调用它,只需调用 exec sp_WhatDatabaseAmICallingFrom 。
标签: sql sql-server stored-procedures