Answers:
我想引用存储过程存储在其中的数据库,即使它是从另一个数据库执行的也是如此。
只需在存储过程中使用一部分或两部分的名称,它将引用包含该存储过程的数据库中的对象。特别是,
对于存储过程中的静态SQL:
不合格的对象名称将相对于包含存储过程的架构进行解析。
由两部分组成的名称将相对于包含存储过程的数据库进行解析。
对于存储过程中的动态SQL:
不合格的对象名称将相对于运行存储过程的用户身份的默认架构(默认情况下为调用者)进行解析。
由两部分组成的名称将相对于包含存储过程的数据库进行解析。
在这两种情况下,db_name()函数都将返回包含存储过程的数据库的名称。
这是我整理的一个简单示例,展示了一些常用功能,这些功能可以使您更接近所需的内容。
/** Create a procedure in master to demonstrate
DB_NAME()
OBJECT_SCHEMA_NAME()
OBJECT_NAME()
@@PROCID
**/
USE [master]
GO
CREATE OR ALTER PROCEDURE dbo.uspTestMe
AS
BEGIN
PRINT 'Database: ' + DB_NAME()
PRINT 'Schema Name: ' + OBJECT_SCHEMA_NAME(@@PROCID)
PRINT 'Procedure Name: ' + OBJECT_NAME(@@PROCID)
END
GO
/** CHANGE Context to TempDB
Execute procedure in master
**/
USE [tempdb]
GO
EXEC master.dbo.uspTestMe
GO
/** Cleanup in master **/
USE [master]
GO
DROP PROCEDURE IF EXISTS dbo.uspTestMe
我想引用存储过程存储在其中的数据库,即使它在另一个数据库中执行也是如此。
您很幸运,因为这是常规/永久性非系统存储过程已经以这种方式工作的方式,实际上您需要竭尽全力让对象在当前数据库中运行。这就是函数的工作方式,只是对于存储过程,您可以选择-将它们标记为“系统存储过程”或创建临时存储过程-而对于功能/视图/触发器/等则没有。
由于内置函数在临时存储过程中的行为与静态SQL略有不同,因此以下示例在UDF和Inline-TVF中使用非临时表进行引用。是的,下面的示例实际上并未测试临时存储过程,但之所以使用非临时表,是因为由于我们有一个行为不同的实例,因此我们需要确保此处不会发生这种行为。在下面的示例中,如果任何一种类型的函数都知道“当前”数据库,则对非临时表的引用将导致错误。
设定
USE [tempdb];
CREATE IF NOT EXISTS TABLE dbo.InTempDB (Col1 INT);
INSERT INTO dbo.InTempDB ([Col1]) VALUES (999);
GO
CREATE
OR ALTER -- comment out if using SQL Server < 2017
FUNCTION dbo.GetDbNameUDF()
RETURNS SYSNAME
AS
BEGIN
DECLARE @DoNothing INT;
SELECT @DoNothing = [Col1] FROM dbo.InTempDB;
RETURN DB_NAME();
END;
GO
CREATE
OR ALTER -- comment out if using SQL Server < 2017
FUNCTION dbo.GetDbNameITVF()
RETURNS TABLE
AS
RETURN
SELECT DB_NAME() AS [DbName],
tmp.[Col1]
FROM dbo.InTempDB tmp;
GO
测试
USE [model];
SELECT DB_NAME() AS [CurrentDB],
tempdb.dbo.GetDbNameUDF() AS [DbNameFromUDF];
-- CurrentDB DbNameFromUDF
-- model tempdb
SELECT DB_NAME() AS [CurrentDB],
*
FROM tempdb.dbo.GetDbNameITVF();
-- CurrentDB DbName Col1
-- model tempdb 999
/* -- clean-up
DROP TABLE dbo.InTempDB;
DROP FUNCTION dbo.GetDbNameUDF;
DROP FUNCTION dbo.GetDbNameITVF;
*/