默认架构允许在不使用架构前缀的情况下选择 dbo 表

SEa*_*986 3 schema sql-server permissions sql-server-2014

我在我的服务器上创建了一个登录名和一个数据库用户,如下所示:

USE master
GO
CREATE LOGIN MyLogin WITH PASSWORD=N'Password123!'
GO
USE AdventureWorks2014
GO
CREATE USER MyLogin FOR LOGIN MyLogin
GO
ALTER USER MyLogin WITH DEFAULT_SCHEMA=HumanResources
GO
GRANT SELECT ON SCHEMA :: Production TO MyLogin
GO
GRANT SELECT ON SCHEMA :: HumanResources TO MyLogin
GO
GRANT SELECT ON SCHEMA :: dbo TO MyLogin
Run Code Online (Sandbox Code Playgroud)

当我作为 MyLogin 登录时,我现在可以在 HumanResources 模式中选择对象而不使用四部分名称(因为 HumanResources 是该用户的默认模式)

SELECT * FROM HumanResources.Department
Run Code Online (Sandbox Code Playgroud)

现在可以在没有架构名称的情况下运行:

SELECT * FROM Department
Run Code Online (Sandbox Code Playgroud)

这可以。如果我然后尝试从生产模式中的表中选择而不使用模式前缀:

SELECT * FROM ProductDescription
Run Code Online (Sandbox Code Playgroud)

我按预期收到错误。这可以通过使用以下方法解决:

SELECT * FROM Production.ProductDescription
Run Code Online (Sandbox Code Playgroud)

因此,基于此,我需要在从默认架构之外的任何表中进行选择时指定架构名称。

那么为什么当我从 dbo 模式中的表中进行选择时,我仍然不需要使用模式前缀吗?

SELECT * FROM DatabaseLog
Run Code Online (Sandbox Code Playgroud)

返回结果

我很迷惑。我认为如果架构名称不在 SELECT 语句中为表添加前缀,则使用默认架构并且从任何其他架构中的表中进行选择将需要架构前缀。

dbo 模式是此规则的例外吗?

Aar*_*and 6

当某些对象位于默认架构中时,您不需要前缀,因为 SQL Server 首先检查默认架构中的非架构前缀对象。然后它将检查dbo模式,因此您实际上可以通过两种不同的方式摆脱这种懒惰。

文档

当使用单部分名称引用数据库对象时,SQL Server 首先查看用户的默认架构。如果在那里找不到对象,SQL Server 会在dbo架构中查找下一个。如果对象不在dbo架构中,则返回错误。

他们说“部分名称”,但这也适用于您引用具有以下模式的对象时:

[server].[database]..[name]
Run Code Online (Sandbox Code Playgroud)

或者

[database]..[name]
Run Code Online (Sandbox Code Playgroud)

这只不过是确认您应该始终指定 schema name总是。