Có thể có được ngăn xếp cuộc gọi thực hiện trong một kích hoạt?


16

Tôi có 10 thủ tục được lưu trữ và mỗi thủ tục thực hiện CHỈ vào một bảngX.

Có thể trong phần thân kích hoạt của bảngX để lấy đối tượng gây ra sửa đổi của bảngX (lưu trữ Proc1 hoặc sp2 hoặc ....) không?

Cảm ơn bạn.

Câu trả lời:


9

Có, có thể xác định mã đang chạy, bằng cách sử dụng chức năng hệ thống @@ Procid và OBRI_NAME tốt hơn (@@ PROCID) để có tên đầy đủ.

Định nghĩa: "Trả về mã định danh đối tượng (ID) của mô-đun Transact-SQL hiện tại. Mô-đun Transact-SQL có thể là một thủ tục được lưu trữ, hàm do người dùng xác định hoặc kích hoạt. @@ PROCID không thể được chỉ định trong các mô-đun CLR hoặc trong- nhà cung cấp truy cập dữ liệu. "

Bạn có thể đọc về nó ở đây .

Một lựa chọn khác là kiểm tra kế hoạch sql của spid hiện tại và lưu thông tin đó vào bảng ghi nhật ký. Một truy vấn mẫu được sử dụng trong mỗi quy trình để lưu dữ liệu kiểm toán sẽ là:

select sp.hostname, sp.program_name, sp.loginame,
    st.text as query_text
from sysprocesses sp
cross apply sys.dm_exec_sql_text(sp.sql_handle) as st  
where sp.spid = @@spid

Có thể có quá nhiều chi tiết ở đó..nhưng tôi tin rằng bạn có ý tưởng.

Một lựa chọn thứ ba sẽ được sử dụng context_info thông tin đến phiên SP hiện tại của. Và liên kết ở đâu đó thông tin bối cảnh được lưu ở đó với mỗi thủ tục. Ví dụ trong thủ tục1 bạn viết 111 vào ngữ cảnh, trong thủ tục2 bạn viết 222 .. và cứ thế.

Nhiều thông tin hơn về bối cảnh_info bạn có thể đọc trong câu hỏi SO này .


1
1) OBarget_NAME (@@ PROCID) trong trình kích hoạt trả về tên trình kích hoạt :(. 2) cần có thông tin ngay tại trình kích hoạt. 3) bối cảnh là một giải pháp. cảm ơn.
garik

1
Vâng, bên trong một trình kích hoạt OBJECT_NAME(@@PROCID)trả về tên kích hoạt, không phải là cuộc gọi Proc.
ProfK

Đây chỉ là một lỗi bình thường. Nó trả về tên của trình kích hoạt, không phải của quy trình gọi như OP yêu cầu
Kỹ sư đảo ngược

Đồng ý, trả lời là sai. CONTEXT_INFO hoạt động nếu bạn có thể sửa đổi quy trình ngược dòng.
Tom Warfield

3

Tôi cũng muốn làm điều này. Cảm ơn câu trả lời. Vì tôi vẫn ở đây, tôi sẽ đăng bài kiểm tra của mình để tiết kiệm thời gian cho người khác :)

CREATE TABLE  Test ( TestID INT )
GO

CREATE TRIGGER TestTrigger ON Test
FOR INSERT
AS

SELECT CAST(CONTEXT_INFO() AS NVARCHAR(128));
GO

CREATE PROCEDURE usp_ProcIDTest
AS

DECLARE @ProcedureName VARBINARY(MAX) = CAST(OBJECT_NAME(@@PROCID) AS VARBINARY(MAX))
SET CONTEXT_INFO @ProcedureName

INSERT INTO Test ( TestID ) VALUES ( 1 ) 

GO

EXEC usp_ProcIDTest
GO

DROP TABLE Test
GO

2

XE cung cấp một cách khác để biết đến ngăn xếp T-SQL mặc dù SQL Server 2008 có thể không hỗ trợ loại sự kiện đã sử dụng. Giải pháp bao gồm kích hoạt, lỗi và phiên XEvent. Tôi lấy ví dụ của Jim Brown để chỉ ra cách nó hoạt động.

Trước hết, tôi đã thử nghiệm giải pháp cho SQL Server 2016 SP2CU2 Dev Edition. SQL Server 2008 hỗ trợ một số EXevent, nhưng tôi không có trường hợp nào để tôi không thể kiểm tra nó.

Ý tưởng là tạo ra lỗi người dùng trong khối thử bắt giả, sau đó bắt lỗi trong phiên XEvent bằng tsql_stackhành động. SQLSERVER.error_reportedLoại XEvent có thể bắt tất cả các lỗi ngay cả khi một khối thử bắt bẫy chúng. Cuối cùng, sys.dm_exec_sql_texttrích xuất các truy vấn T-SQL từ truy vấn xử lý tsql_stackhành động nào đưa ra.

Một ví dụ từ câu trả lời của Jim Brown, mà tôi đã phát triển, được hiển thị bên dưới. Một kích hoạt làm tăng lỗi với văn bản 'bắt tôi'. Phiên XEvent bắt lỗi chỉ với văn bản như 'bắt tôi'.

CREATE TABLE  Test ( TestID INT )

GO

CREATE TRIGGER TestTrigger ON Test
FOR INSERT
AS
BEGIN TRY
    SET XACT_ABORT OFF; -- REALLY IMPORTANT!
    /* make an catching a great deal more interesting */
    DECLARE @TestID NVARCHAR(MAX) ;
    SELECT TOP (1) @TestID = CAST(ins.TestID AS NVARCHAR(MAX)) FROM inserted AS ins ;
    RAISERROR (N'catch_me TestID = "%s"' , 11 , 0 , @TestID) ;
END TRY BEGIN CATCH /* NOTHING TO DO */ END CATCH

GO

CREATE PROCEDURE usp_ProcIDTest
AS
INSERT INTO Test ( TestID ) VALUES ( 1 ) 

GO

CREATE PROCEDURE usp_RootProcIDTest
AS
EXEC usp_ProcIDTest

GO

-- This XEvent session definition was kindly provided by XEvent 'New Session' wizard.
CREATE EVENT SESSION [catch_insertion_into_Test] ON SERVER 
ADD EVENT sqlserver.error_reported(
    ACTION(package0.callstack,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack,sqlserver.username,sqlserver.context_info,sqlserver.plan_handle)
    WHERE ([message] like N'catch_me%'))
ADD TARGET package0.ring_buffer(SET max_memory=(10240))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)

GO

Bây giờ, nếu bạn khởi chạy phiên XEvent (SSMS, Object Explorer, Management, Extended Events, Sairs, Catch_inserts_into_Test), hãy thực thi usp_RootProcIDTest và xem bộ đệm vòng của phiên XEvent, bạn sẽ thấy XML bao gồm nút <action name="tsql_stack" package="sqlserver">. Có một chuỗi các nút khung. Đặt các giá trị của handlethuộc tính 's vào hàm hệ thống' sys.dm_exec_sql bản 'và voilà:

-- REPLACE MY HANDLES WITH YOURS
SELECT * FROM sys.dm_exec_sql_text(0x03000800D153096910272C01A6AA000000000000000000000000000000000000000000000000000000000000);
SELECT * FROM sys.dm_exec_sql_text(0x030008000A78FD6912272C01A6AA000001000000000000000000000000000000000000000000000000000000);
SELECT * FROM sys.dm_exec_sql_text(0x03000800439CF16A13272C01A6AA000001000000000000000000000000000000000000000000000000000000);

Một ví dụ ngăn xếp cuộc gọi thực hiện

XEvent cho phép bạn làm nhiều hơn thế này! Đừng bỏ lỡ cơ hội để tìm hiểu chúng!

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.