Dapatkah prosedur tersimpan merujuk pada basis data tempat penyimpanannya?

8

Misalkan saya memiliki prosedur tersimpan yang digandakan, dengan beberapa modifikasi, di beberapa basis data. Dan saya ingin referensi database di mana prosedur tersimpan disimpan, bahkan jika dieksekusi di database lain.

Apakah ada cara untuk mengambil path lengkap (..) atau mengambil database tempat prosedur tersimpan disimpan, daripada database saat ini?

Jim Clark
sumber
Saya tidak tahu bahwa proc mengeksekusi dalam konteks basis data di mana ia tinggal dan saya ingin memastikan bahwa menjalankannya dalam database lain tidak akan memengaruhi database Anda.
Jim Clark

Jawaban:

13

Saya ingin mereferensikan basis data di mana prosedur tersimpan disimpan, walaupun itu dijalankan [dari] basis data lain.

Cukup gunakan satu bagian atau dua bagian nama dalam prosedur tersimpan, dan itu akan merujuk objek dalam database yang berisi prosedur tersimpan. Khususnya,

Untuk SQL statis dalam prosedur tersimpan:

  • Nama objek yang tidak memenuhi syarat akan menyelesaikan relatif terhadap skema yang berisi prosedur tersimpan.

  • Nama dua bagian akan diselesaikan relatif terhadap database yang berisi prosedur tersimpan.

Untuk SQL dinamis dalam prosedur tersimpan:

  • Nama objek yang tidak memenuhi syarat akan menyelesaikan relatif terhadap skema default identitas pengguna yang menjalankan prosedur tersimpan (secara default, pemanggil).

  • Nama dua bagian akan diselesaikan relatif terhadap database yang berisi prosedur tersimpan.

Fungsi db_name () akan mengembalikan nama database yang berisi prosedur tersimpan dalam kedua kasus.

David Browne - Microsoft
sumber
4

Berikut adalah contoh cepat yang saya kumpulkan menunjukkan fungsi-fungsi umum yang digunakan untuk mendekati apa yang Anda cari.

/** 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 
Jonathan Fite
sumber
0

Menambahkan ke jawaban David Browne yang luar biasa :

Saya ingin mereferensikan basis data tempat prosedur tersimpan disimpan, bahkan jika dieksekusi di basis data lain.

Anda beruntung karena ini adalah cara yang biasa / permanen, prosedur yang tersimpan non-sistem sudah bekerja dengan cara ini, dan Anda benar-benar harus keluar dari cara Anda untuk mendapatkan objek untuk beroperasi di DB saat ini. Ini adalah bagaimana fungsi bekerja juga, hanya saja dengan prosedur tersimpan, Anda memiliki opsi - menandainya sebagai "prosedur tersimpan sistem" atau membuat prosedur tersimpan sementara - yang tidak Anda miliki dengan fungsi / tampilan / pemicu / dll.

Karena fungsi bawaan berperilaku sedikit berbeda dari SQL statis dalam prosedur tersimpan sementara, contoh berikut menggunakan tabel non-sementara untuk referensi di UDF dan Inline-TVF. Benar, contoh berikut ini tidak benar-benar menguji prosedur tersimpan sementara, tetapi alasan saya menggunakan tabel non-sementara adalah karena karena kita memiliki satu contoh perilaku yang berbeda, kita perlu memastikan bahwa perilaku seperti itu tidak terjadi di sini. Dalam contoh berikut, jika salah satu jenis fungsi menyadari database "saat ini", maka referensi ke tabel non-sementara akan menyebabkan kesalahan.

MENDIRIKAN

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

UJI

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;
*/
Solomon Rutzky
sumber