存储过程可以引用存储它的数据库吗?


8

假设我有一个存储过程,它在几个数据库中进行了重复的修改。而且我想引用存储过程存储在其中的数据库,即使它在另一个数据库中执行也是如此。

有没有办法检索完整路径(..)或以其他方式检索存储过程的数据库,而不是当前数据库?


我不知道,在数据库方面的PROC执行它生活的地方,我想确保在而在另一个数据库不会影响你在数据库中运行它。
吉姆·克拉克

Answers:


13

我想引用存储过程存储在其中的数据库,即使它是从另一个数据库执行的也是如此。

只需在存储过程中使用一部分或两部分的名称,它将引用包含该存储过程的数据库中的对象。特别是,

对于存储过程中的静态SQL:

  • 不合格的对象名称将相对于包含存储过程的架构进行解析。

  • 由两部分组成的名称将相对于包含存储过程的数据库进行解析。

对于存储过程中的动态SQL:

  • 不合格的对象名称将相对于运行存储过程的用户身份的默认架构(默认情况下为调用者)进行解析。

  • 由两部分组成的名称将相对于包含存储过程的数据库进行解析。

在这两种情况下,db_name()函数都将返回包含存储过程的数据库的名称。


4

这是我整理的一个简单示例,展示了一些常用功能,这些功能可以使您更接近所需的内容。

/** 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 

0

除了David Browne的出色答案之外

我想引用存储过程存储在其中的数据库,即使它在另一个数据库中执行也是如此。

您很幸运,因为这是常规/永久性非系统存储过程已经以这种方式工作的方式,实际上您需要竭尽全力让对象在当前数据库中运行。这就是函数的工作方式,只是对于存储过程,您可以选择-将它们标记为“系统存储过程”或创建临时存储过程-而对于功能/视图/触发器/等则没有。

由于内置函数在临时存储过程中的行为与静态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;
*/
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.