對象名稱(模塊)是resolved based on the owner of the stored procedure(模塊)不是執行用戶。因此,如果你引用一個存儲過程中一個名爲TABLE_1表聲明:
CREATE PROCEDURE dbo.usp_GetTable_1 AS SELECT * FROM [TABLE_1]
然後解析表名稱爲[DBO] [TABLE_1]。
如果你願意忍受動態SQL,那麼你可以做這樣的事情:
--Stored procedure uses dynamic SQL so object name resolution rules inside
--modules does not apply
CREATE PROCEDURE dbo.usp_GetTable_1 AS
EXEC sp_executesql N'SELECT * FROM [TABLE_1]'
GO
--create Table_1 in two schemas
CREATE TABLE [Com1].[Table_1](
[Id] [int] NOT NULL,
[Schema] As OBJECT_SCHEMA_NAME (OBJECT_ID('[Com1].[Table_1]'))
) ON [PRIMARY]
GO
CREATE TABLE [Com2].[Table_1](
[Id] [int] NOT NULL,
[Schema] As OBJECT_SCHEMA_NAME (OBJECT_ID('[Com2].[Table_1]'))
) ON [PRIMARY]
GO
--Now create two users, defaulting each to one of the schemas
CREATE USER Com1User WITHOUT LOGIN WITH default_schema = [Com1]
CREATE USER Com2User WITHOUT LOGIN WITH default_schema = [Com2]
--set the ownership of the schemas to match
ALTER AUTHORIZATION ON SCHEMA::[Com1] TO [Com1User]
ALTER AUTHORIZATION ON SCHEMA::[Com2] TO [Com2User]
--Adding the users to the db_owner role naively allows executing dbo schema modules
--for demo purposes. Alternatively grant execution to specific dbo modules
EXEC sp_addrolemember N'db_owner', N'Com1User'
EXEC sp_addrolemember N'db_owner', N'Com2User'
--Set the execution context and call the procedure
EXECUTE AS User = 'Com1User'
EXEC dbo.usp_GetTable_1
REVERT;
--Set the execution context and call the procedure
EXECUTE AS User = 'Com2User'
EXEC dbo.usp_GetTable_1
REVERT;
就個人而言,我不是這個使用模式的忠實粉絲。架構是爲了安全而在較小程度上 - 避免大量數據庫對象的名稱衝突。我個人更喜歡將每組對象放在不同的數據庫上,並使用不同的用戶登錄與默認數據庫來控制名稱解析。