存储过程(模块)内的对象名称是根据存储过程(模块)的所有者而不是执行用户来解析的。因此,如果您在声明为的存储过程中引用名为 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;
就个人而言,我不是这种使用模式的忠实粉丝。模式是为了安全,在较小程度上是为了避免大量数据库对象的名称冲突。我个人更喜欢将每组对象放在不同的数据库上,并使用不同的用户登录名和默认数据库来控制名称解析。