如何找到最後一條sql語句的數據庫上下文?
我想從下面的程式碼中找出執行最後一個命令的數據庫的名稱是什麼。
在這種情況下,我正在尋找
my_other_database
.他有什麼辦法找到這個嗎?我應該查看任何 DMV 以獲取此資訊嗎?
另外,如果更新被包裝在動態 sql 中,那麼是否可以跟踪它呢?
use my_database go begin tran t1 UPDATE my_other_database.REF.applicationReference SET uploadPaperReferences = 0 WHERE REFERENCEID IN ( 69361, 69690, 69354, 69358, 69362, 69732, 69863, 70187 ) commit tran t1
我想完成什麼?在下面的範例中,最後我列印出伺服器的名稱和我所在的數據庫的名稱:
但在下面的範例中,雖然我在技術上是在數據庫內部
cola
,但聲明是apcore.upl.applicationDocument
,apcore
是另一個數據庫。有沒有辦法列印出來
apcore
,而不是cola
?SET NOCOUNT OFF SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED BEGIN TRAN T1 PRINT '' PRINT 'AFTER BEGIN TRAN' PRINT '' PRINT '@@TRANCOUNT: ' + CAST(@@TRANCOUNT AS VARCHAR) PRINT '@@SERVERNAME: ' + CAST(@@SERVERNAME AS VARCHAR) + CHAR(10) + 'Databasename: ' + DB_NAME() PRINT '' DECLARE @row INT USE COLA SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED update t set documentstateid = 5 from apcore.upl.applicationDocument t where applicationid in ( 319761 ,320455 ,333433 ,351642 ,371539 ,372508 ) and documentStateId not in (1,5) SELECT @row = @@ROWCOUNT PRINT '' PRINT 'AFTER RUNNING THE UPDATE(s)' PRINT '' PRINT 'The number of rows updated:' + SPACE(1) + CAST(@row as varchar) PRINT '@@TRANCOUNT: ' + CAST(@@TRANCOUNT AS VARCHAR) PRINT 'Server Name is:' + space(1) + @@SERVERNAME + CHAR(10) + 'Databasename: ' + DB_NAME() COMMIT TRAN T1 PRINT '' PRINT 'AFTER COMMIT' PRINT '' PRINT '@@TRANCOUNT: ' + CAST(@@TRANCOUNT AS VARCHAR) PRINT 'Server Name is:' + space(1) + @@SERVERNAME + CHAR(10) + 'Databasename: ' + DB_NAME()
即席查詢在已登錄或最近更改為通過
USE
語句的數據庫中執行。在儲存過程或函式中執行的查詢在其所在模組所在的數據庫中執行。
例如:
USE [tempdb]; -- DROP PROCEDURE dbo.CurrentDatabaseTest; GO CREATE PROCEDURE dbo.CurrentDatabaseTest AS SET NOCOUNT ON; SELECT db.[database_id], db.[name] FROM sys.dm_exec_sessions es INNER JOIN sys.databases db ON db.[database_id] = es.[database_id] WHERE es.[session_id] = @@SPID; GO USE [model]; SELECT db.[database_id], db.[name] FROM sys.dm_exec_sessions es INNER JOIN sys.databases db ON db.[database_id] = es.[database_id] WHERE es.[session_id] = @@SPID; EXEC tempdb.dbo.CurrentDatabaseTest; GO
執行上述應返回以下內容:
database_id name 3 model database_id name 2 tempdb
您有時可以從以下查詢中獲取數據庫 ID,但並非總是如此:
SELECT txt.* FROM sys.dm_exec_connections con OUTER APPLY sys.dm_exec_sql_text(con.[most_recent_sql_handle]) txt --WHERE con.[session_id] = @@SPID;
文件指出,關於返回
dbid
欄位的值:對於即席和準備好的 SQL 語句,編譯語句的數據庫的 ID。
但是,我的測試表明,
NULL
如果最後一個語句是臨時的。啊,但我剛看到一張紙條,上面寫著:
dbid無法從sql_handle確定即席查詢。要確定臨時查詢的dbid ,請改用plan_handle。
不幸的是,您無法
plan_handle
從sys.dm_exec_connections
或中獲得 asys.dm_exec_sessions
。您可以從 獲取它sys.dm_exec_requests
,但只有在會話執行查詢時才會出現行。查詢結束後,該行不再在該 DMV 中。如果您使用該 DMV 來獲取目前會話的值,那麼它將始終是您目前所在的數據庫,因為查詢將是您正在執行以查找數據庫的查詢,在這種情況下,您不妨只是選擇或database_id
使用sys.dm_exec_sessions
內置DB_NAME()
和DB_ID()
函式(不為它們傳遞任何參數)。更新解決問題中的附加資訊
$$ i $$在下面的範例中,雖然我在技術上是在數據庫內部
cola
,但語句是apcore.upl.applicationDocument
,apcore
是另一個數據庫。是的,這是兩個不同的數據庫,但我認為你誤解了這裡發生的事情。該語句引用了一個對象。但是考慮一個多對象查詢:
update t set documentstateid = 5 from apcore.upl.applicationDocument t INNER JOIN other_db.dbo.some_table st ON st.column = t.column where applicationid in (...
現在有兩個數據庫被引用,你都不在其中。
如果該表上有觸發器,或者查詢使用了該
OUTPUT
子句,或者您啟用了快照隔離,那麼tempdb
也涉及到。唯一實際存在的上下文是您目前所在的數據庫。
就模組(儲存過程、觸發器、函式和視圖)而言,上下文是它們所在的數據庫,無論它們是從哪裡呼叫的。
但是,模組有兩個例外:
- 駐留在
master
並標記為“系統儲存過程”的儲存過程具有執行它們的位置的上下文。- 臨時儲存過程是一種奇怪的情況,因為它們中的查詢在創建它們的 DB 中執行(
CREATE PROCEDURE
不一定是 時的目前 DBtempdb
),但係統函式(例如DB_NAME()
,DB_ID()
等)獲取目前DB。