如何在存储过程执行时获取在该存储过程中执行的数据库的名称?

J.D*_*.D. 3 sql-server stored-procedures dynamic-sql sql-server-2008-r2

奇怪的问题?...也许,但我有需要。:)

我有一个存储过程,我想在任何数据库中普遍使用。存储过程生成一些动态 SQL,然后在作为此过程中的参数之一传入的数据库中执行该 SQL。

但是我想让数据库参数成为可选的,并且当没有传入数据库名称时,我希望动态 SQL 在调用过程本身的同一个数据库中执行。(请记住,此过程可以跨数据库执行,而不是在该过程本身所在的同一数据库中执行。)

Aar*_*and 6

您可以通过动态构建[database].sys.sp_executesql命令来轻松告诉特定数据库中的动态 SQL 执行:

USE your_database;
GO

CREATE PROCEDURE dbo.DatabaseNameOptional
    @db sysname = NULL
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @sql nvarchar(max) = N'SELECT DB_NAME(); /* other stuff */'

  DECLARE @exec nvarchar(770) = COALESCE(@db, DB_NAME())
    + N'.sys.sp_executesql';

  -- alternatively, just leave DB_NAME() out of it:

  --DECLARE @exec nvarchar(770) = COALESCE(@db, N'')
  --  + N'sys.sp_executesql';

  EXEC @exec @sql;
END
GO
Run Code Online (Sandbox Code Playgroud)

试试看:

USE your_database;
GO

EXEC dbo.DatabaseNameOptional;
GO  -- output = your_database

EXEC dbo.DatabaseNameOptional @db = N'master';
GO  -- output = master

USE tempdb;
GO

EXEC your_database.dbo.DatabaseNameOptional;
GO  -- output = your_database

EXEC your_database.dbo.DatabaseNameOptional @db = N'master';
GO  -- output = master
Run Code Online (Sandbox Code Playgroud)

但是,在过程的执行上下文中,不,我认为没有任何方法可以确定调用源自何处(或在该上下文中运行)。这就是在 master 中使用系统标记过程的好处 - 如果这是您想要的功能,您需要确定“将对象放入 master”是否比“没有得到我想要的”更令人讨厌。

  • @MikeBeaton 如果您将存储过程放在 master 中,在它前面加上 `sp_`,并将其标记为系统对象,那么从任何数据库调用它都会使其在调用数据库的上下文中执行。没有办法(同样,我知道)在任何用户数据库的存储过程中模仿这种行为。 (2认同)
  • @MikeBeaton 是的。我没有在原始答案中包含该选项,因为它已经存在于其他答案中。我提供了一个不同的选项,以防 OP 不想将对象放在 master 中(或者不能,由于策略、权限或使用 Azure SQL 数据库)。 (2认同)