, , Sql2012.
, ('VIEW SERVER STATE'), , , .
USE [DB_A];
GO
CREATE FUNCTION dbo.GetCallingDbCatName()
RETURNS nvarchar(128)
WITH EXECUTE AS SELF
AS
BEGIN
DECLARE @result nvarchar(128);
SELECT TOP 1 @result = DB_NAME(resource_database_id)
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
AND resource_type = 'DATABASE'
AND request_owner_type = 'SHARED_TRANSACTION_WORKSPACE'
ORDER BY IIF(resource_database_id != DB_ID(), 0, 1);
RETURN @result;
END
GO
USE [DB_A];
SELECT DB_A.dbo.GetCallingDbCatName();
USE [DB_B];
SELECT DB_A.dbo.GetCallingDbCatName();
USE [DB_C];
SELECT DB_A.dbo.GetCallingDbCatName();
, dbcat.
2019-07-26 - : , ( ) dbcat, master tempdb, SHARED_TRANSACTION_WORKSPACE. ( , )
SHARED_TRANSACTION_WORKSPACE - SQL Server EXCLUSIVE_TRANSACTION_WORKSPACE , , , , . , SQL Server tempdb, , . , tempdb, , , , , SHARED_TRANSACTION_WORKSPACE .
, , DB_A DB_B, 2 ; DB_B, , DB_A, /. , (DB_A func DB_B, func DB_C, dbcat; ORDER BY DB_A DB_B.)
Finally, this solution also works with the CLR method. Do not forget to execute the Sql function of the “shell” with sufficient permission to use db_tran_locks, and the attribute SqlFunctionshould have “SystemDataAccess = SystemDataAccessKind.Read”. The context connection uses the same SPID as the caller, and it is located in the dbcat where the assembly lives (and therefore where the wrapper function / sproc lives, which provides the CLR method.)
For reference, here is my test CLR method:
[SqlFunction(IsDeterministic = false, DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.Read), SqlMethod(OnNullCall = true)]
public static SqlString GetCallingDbcatName()
{
string sqlResult = "";
using (var connection = new System.Data.SqlClient.SqlConnection("context connection=true"))
{
connection.Open();
var sqlCmd = connection.CreateCommand();
sqlCmd.CommandText = @"
SELECT TOP 1 DB_NAME(resource_database_id)
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
AND resource_type = 'DATABASE'
AND request_owner_type = 'SHARED_TRANSACTION_WORKSPACE'
ORDER BY IIF(resource_database_id != DB_ID(), 0, 1); ";
sqlResult = sqlCmd.ExecuteScalar().ToString();
}
return sqlResult;
}