用户/架构分离
SQL Server 2000 没有架构的概念,而 ANSI SQL-99 规范将架构定义为单个主体所拥有的所有数据库对象集合,而且该主体形成了对象的一个命名空间。架构就是数据库对象的容器(如表、视图、存储过程、函数、类型和触发器等)。它的功能与.NTE Framework 和 XML 中的命名空间函数非常类似,该函数可将对象进行分组,以便数据库能够重用对象名称,如允许在一个数据库中同时存在 dbo.Customer 和 Fred.Customer,也可对不同所有者的对象进行分组。
注意:需要用到目录视图,如 sys.database_sys.principals、sys.schemas 和sys.objects 等。原因在于 sysobjects 旧系统表不支持架构,因此不支持U/S分离。此外,不赞成使用旧目录视图,在 SQL Server 的未来版本中它们将被删除。
需要修改对象的所有权时,例如 Alice 离开公司而 Lucinda 接手了 Alice 的工作,此时SQL Server 2000 中用户和架构的融合会产生一个问题。系统管理员必须将 Alice 拥有的所有对象的所有者改为Lucinda。更成问题的是,则 Lucinda 拥有了表的所有权后,还必须将任何引用 Alice.Table1 的Transact-SQL 或客户端应用程序代码改为引用 Lucinda.Table1。根据 Alice 拥有的对象数量以及内部嵌有该名称的应用程序数量,这可能是一项繁重的工作。Microsoft 公司一直建议内置的 dbo 用户要拥有所有的数据库对象,以避免产生这些问题。与修改许多对象和客户端应用程序相比,修改数据库的所有权要容易得多。
注意:不要被 SQL Server 2000 CREATE SCHEMA 语句迷惑。它只是一种简单的方法,用以创建特殊用户拥有的表和视图,以及授予权限。可以利用该语句命名架构的所有者,但不能命名架构。SQL Server 仍不可避免地将所有者链接到架构,这要面对修改所有权带来的所有问题。
SQL Server 2008 通过分离用户和架构克服了这些问题,并实施了 SQL-99 架构,如图9底部所示。利用新增的 CREATE USER DDL 创建 Alice 新用户时,SQL Server 不再自动创建使用相同名称的架构。反之,必须显式创建架构,并将其所有权分配用户。
由于图示的所有的数据库对象都包含于 Schema1 架构中,就是 Alice 最初拥有的架构,因此只须将架构的所有者改为 Lucinda,就可以方便地修改所有架构对象的所有权。每位用户也都被分配默认架构,这样 SQL Server 将假定没有架构引用且按照名称引用的任何对象都位于默认架构中。在图9的底部,如果 Alice 使用 Schema1 作为默认架构,她就可将该表命名为 Schema1.Table1 或Table1。Carol 用户可能没有与其名字关联的默认架构,必须将该表命名为 Schema1.Table1。没有默认预定义架构的任何用户都使用 dbo 作为默认架构。
在 SQL Server 2008 中,完全合格的对象名称由4部分组成,这与旧版SQL Server 中的对象名称类似:
server.database.schema.object
与旧版类似,如果对象所在服务器与运行代码的服务器同名,则可忽略服务器名称。如果连接打开了同名数据库,则可忽略数据库名称。如果使用当前用户的默认架构或架构为 dbo 所拥有,则可忽略架构名称,因为这是 SQL Server 尝试消除对象名称歧义时最后用过的架构。
可以利用 CREATE USER 语句而非 sp_adduser 语句创建新用户。此系统存储过程仍然是为了实现向后兼容性,但已进行了少许修改,以遵循用户与架构分离的新原则。sp_adduser 创建的架构与新用户名或应用程序角色同名,并将该架构作为用户的默认架构,这与 SQL Server 2000 的行为类似,但提供了分离的架构。
注意:使用 ALTER AUTHORIZATION 语句时,可能会产生这种情况:“您”拥有“我的”架构中的表(或反之)。这个问题具有重大的隐含意义。例如,谁拥有该表的触发器,您还是我?底部的代码行可以设计得非常巧妙,以发现架构范围对象或类型的真正所有者。有两种方式可以避开此问题:
利用 OBJECTPROPERTY(id,”OwnerId”)发现对象的真正所有者。
利用 TYPEPROPERTY(type,”OwnerId”)发现类型的真正所有者。
SQL Server 2008 利用同义词帮助减少击键次数。可以利用两部分、三部分或四部分完整对象名为任何对象创建同义词。SQL Server 使用同义词访问已定义的对象。在下列代码中,“History”同义词表示在AdventureWorks 数据库中指定的 schema.table。SELECT 语句返回EmployeeDepartmentHistory 表的内容。
GO
CREATE SYNONYM History FOR HumanResources.EmployeeDepartmentHistory
SELECT * FROM History
注意:如果其他人准备使用同义词,则管理员或所有者必须为其授予权限。针对视图、表或表值函数,可对同义词应用GRANT SELECT。针对过程或标量函数,可对同义词应用 GRANT EXECUTE,诸如此类。
也可通过以下代码,为完整的四部分名称定义“History”同义词:
CREATE SYNONYM History
FOR MyServer.AdventureWorks.HumanResources.EmployeeDepartmentHistory
假设当前的用户拥有使用同义词的权限以及读取表的权限,则使用类似的四部分全名即可在其他数据库上下文中使用同义词:
USE pubs
SELECT * FROM AdventureWorks..History
还要注意,如果不提供架构名称作为新同义词名称的一部分,它将成为默认架构的一部分。