我在单个SQL Server 2008 R2上有许多不同的数据库。为了论证,让我们称它们为DB_A,DB_B和DB_C。我被要求开发为存储过程,它将存在于DB_A上。此存储过程将用于删除和创建索引,并在DB_A上的表中存储有关索引的一些额外信息。当从DB_C或DB_C调用此存储过程时,它将能够在调用数据库上删除并创建索引,但在DB_A上的表中存储有关索引的额外信息。
这就是我想要做的事情:我希望存储过程能够获取调用数据库的名称,而不必请求数据库名称作为参数。
这是一个简单的例子:
USE [DB_A]
CREATE PROC sp_WhatDatabaseAmICallingFrom
AS
BEGIN
DECLARE @calling_db NVARCHAR(128)
SET @calling_db = DB_NAME()
PRINT 'calling database: ' + @calling_db
END
当我在DB_A ...
中执行存储过程时EXEC sp_WhatDatabaseAmICallingFrom
...它返回:“调用数据库:DB_A ”
当我在DB_B中执行存储过程...
时USE DB_B
GO
EXEC DB_A.dbo.sp_WhatDatabaseAmICallingFrom
...它返回:“调用数据库:DB_A ”。
在阅读了各种SQL Server元数据函数之后,这正是它应该做的。但我想要的是更改代码,以便将@calling_db设置为调用数据库的名称,以便我的示例存储过程将打印:“调用数据库:DB_B ”。
不幸的是,我找不到任何能够做到这一点的元数据功能。关于如何做到这一点的任何想法?
答案 0 :(得分:4)
要在当前连接的上下文中运行SP,您需要在master
数据库上创建SP并使其成为系统对象。
USE MASTER
GO
CREATE PROC sp_WhatDatabaseAmICallingFrom
AS
BEGIN
DECLARE @calling_db NVARCHAR(128)
SET @calling_db = DB_NAME()
PRINT 'calling database: ' + @calling_db
END
GO
EXEC sp_ms_marksystemobject 'sp_WhatDatabaseAmICallingFrom'
GO
检查它的工作原理:
USE [DB_A]
GO
EXEC sp_WhatDatabaseAmICallingFrom
GO
答案 1 :(得分:3)
我知道这个帖子很老了,但我发现了一些至少帮助我的东西。
如果您正在使用DB_A并在DB_B中调用存储过程,如:
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:clipChildren="false">
<ImageView
android:layout_marginLeft="-10dp"
android:background="@drawable/some_picture"
android:layout_width="50dp"
android:layout_height="50dp"/>
</android.support.v7.widget.CardView>
我找到获取“调用数据库”id的唯一方法是在存储过程内对sys.dm_tran_locks运行select。 request_session_id应该是你的spid,resource_type应该是DATABASE,request_owner_type应该是SHARED_TRANSACTION_WORKSPACE。对于每个连接的会话,这种共享锁始终存在于数据库中。查询将类似于:
USE DB_A
EXEC db_b.dbo.sproc
虽然这要求执行用户至少拥有服务器上的VIEW SERVER STATE权限。在我的情况下,这不是一个问题..
答案 2 :(得分:0)
基于Mike的答案,这是在Sql2012中有效的解决方案的示例。
您必须在以具有足够权限(“查看服务器状态”)的用户身份登录时创建功能,但是使用该功能的用户仅需要权限才能执行该功能本身。
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(); --"DB_A"
USE [DB_B];
SELECT DB_A.dbo.GetCallingDbCatName(); --"DB_B"
USE [DB_C];
SELECT DB_A.dbo.GetCallingDbCatName(); --"DB_C"
从那里,您应该能够构建所需的实际功能,而无需污染 master dbcat。