ストアドプロシージャは、それが格納されているデータベースを参照できますか?


8

複数のデータベースで、いくつかの変更を加えて複製されたストアード・プロシージャーがあるとします。また、別のデータベースで実行されている場合でも、ストアドプロシージャが格納されているデータベースを参照したいと思います。

現在のデータベースではなく、フルパス(..)を取得する方法、またはストアドプロシージャが格納されているデータベースを取得する方法はありますか?


私はそれが住んでいると私は別のデータベースにしばらくそれを実行すると、あなたがしていたデータベースに影響を与えないことを確認するデータベースのコンテキストでそのPROCの実行を知りませんでした。
ジム・クラーク

回答:


13

別のデータベースから実行されたとしても、ストアドプロシージャが格納されているデータベースを参照したい。

ストアドプロシージャで1部構成または2部構成の名前を使用するだけで、ストアドプロシージャを含むデータベース内のオブジェクトを参照します。特に、

ストアドプロシージャの静的SQLの場合:

  • 修飾されていないオブジェクト名は、ストアドプロシージャを含むスキーマに関連して解決されます。

  • 2部構成の名前は、ストアード・プロシージャーを含むデータベースに関連して解決されます。

ストアドプロシージャの動的SQLの場合:

  • 修飾されていないオブジェクト名は、ストアドプロシージャを実行しているユーザーIDのデフォルトスキーマ(デフォルトでは、呼び出し元)を基準に解決されます。

  • 2部構成の名前は、ストアード・プロシージャーを含むデータベースに関連して解決されます。

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

追加デビッド・ブラウンの優れた答え

別のデータベースで実行されている場合でも、ストアドプロシージャが格納されているデータベースを参照したい。

これは、通常の/永続的な非システムストアドプロシージャが既にこのように機能しており、実際にオブジェクトを現在のDBで動作させるために邪魔になる必要があるため、幸運です。これが関数の機能です。ストアドプロシージャでは、「システムストアドプロシージャ」としてマークしたり、一時的なストアドプロシージャを作成したりするオプションがあります。これは、関数、ビュー、トリガーなどにはありません。

組み込み関数は一時ストアドプロシージャの静的SQLとは少し異なる動作をするため、次の例では、非一時テーブルを使用してUDFとInline-TVFの両方で参照しています。確かに、次の例では一時ストアドプロシージャを実際にテストしていませんが、非一時テーブルを使用したのは、異なる動作のインスタンスが1つあるため、そのような動作がここで発生しないようにする必要があるためです。次の例では、いずれかのタイプの関数が「現在の」データベースを認識している場合、非一時テーブルへの参照がエラーの原因になります。

セットアップ

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;
*/
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.