Một thủ tục được lưu trữ có thể tham chiếu cơ sở dữ liệu mà nó được lưu trữ không?


8

Giả sử tôi có một thủ tục được lưu trữ được sao chép, với một số sửa đổi, trong một số cơ sở dữ liệu. Và tôi muốn tham chiếu cơ sở dữ liệu trong đó thủ tục được lưu trữ được lưu trữ, ngay cả khi nó được thực thi trong cơ sở dữ liệu khác.

Có cách nào để truy xuất đường dẫn đầy đủ (..) hoặc truy xuất cơ sở dữ liệu trong đó thủ tục được lưu trữ được lưu trữ, thay vì cơ sở dữ liệu hiện tại không?


Tôi không biết rằng Proc thực thi trong bối cảnh cơ sở dữ liệu nơi nó sống và tôi muốn đảm bảo rằng việc chạy nó trong khi ở một cơ sở dữ liệu khác sẽ không ảnh hưởng đến cơ sở dữ liệu mà bạn đang ở.
Jim Clark

Câu trả lời:


13

Tôi muốn tham chiếu cơ sở dữ liệu trong đó thủ tục được lưu trữ được lưu trữ, ngay cả khi nó được thực thi [từ] cơ sở dữ liệu khác.

Chỉ cần sử dụng tên một phần hoặc hai phần trong thủ tục được lưu trữ và nó sẽ tham chiếu các đối tượng trong cơ sở dữ liệu chứa thủ tục được lưu trữ. Đặc biệt,

Đối với SQL tĩnh trong một thủ tục được lưu trữ:

  • Tên đối tượng không đủ tiêu chuẩn sẽ phân giải liên quan đến lược đồ chứa thủ tục được lưu trữ.

  • Tên hai phần sẽ giải quyết liên quan đến cơ sở dữ liệu chứa thủ tục được lưu trữ.

Đối với SQL động trong một thủ tục được lưu trữ:

  • Tên đối tượng không đủ tiêu chuẩn sẽ phân giải liên quan đến lược đồ mặc định của danh tính người dùng đang chạy thủ tục được lưu trữ (theo mặc định, người gọi).

  • Tên hai phần sẽ giải quyết liên quan đến cơ sở dữ liệu chứa thủ tục được lưu trữ.

Hàm db_name () sẽ trả về tên của cơ sở dữ liệu chứa thủ tục được lưu trữ trong cả hai trường hợp.


4

Dưới đây là một ví dụ nhanh mà tôi kết hợp với nhau để hiển thị các chức năng phổ biến được sử dụng để gần với những gì bạn đang tìm kiếm.

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

Thêm vào câu trả lời tuyệt vời của David Browne :

Tôi muốn tham chiếu cơ sở dữ liệu trong đó thủ tục được lưu trữ được lưu trữ, ngay cả khi nó được thực thi trong cơ sở dữ liệu khác.

Bạn rất may mắn vì đây là cách các quy trình được lưu trữ thường xuyên / vĩnh viễn, không có hệ thống đã hoạt động theo cách này và bạn thực sự cần phải thực hiện theo cách của mình để khiến các đối tượng hoạt động trong DB hiện tại. Đây là cách các chức năng hoạt động tốt, chỉ là với các thủ tục được lưu trữ, bạn có các tùy chọn - đánh dấu chúng là "thủ tục lưu trữ hệ thống" hoặc tạo các thủ tục được lưu trữ tạm thời - mà bạn không có chức năng / lượt xem / trình kích hoạt / v.v.

Do các hàm dựng sẵn hoạt động hơi khác so với SQL tĩnh trong các thủ tục được lưu trữ tạm thời, ví dụ sau sử dụng bảng không tạm thời để tham chiếu trong cả UDF và Inline-TVF. Đúng, ví dụ sau đây không thực sự kiểm tra các thủ tục được lưu trữ tạm thời, nhưng lý do tôi sử dụng bảng không tạm thời là vì chúng ta có một trường hợp khác nhau về hành vi, chúng ta cần đảm bảo rằng hành vi đó không xảy ra ở đây. Trong ví dụ sau, nếu một trong hai loại hàm đã biết về cơ sở dữ liệu "hiện tại", thì tham chiếu đến bảng không tạm thời sẽ gây ra lỗi.

THIẾT LẬP

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

KIỂM TRA

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;
*/
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.