DBA必读:SQL Server 2008安全概述(二)
DBA必读:SQL Server 2008安全概述(二)
4.3 角色和权限
要想知道在SQL Server中可用的权限的数目,你可以调用fn_builtin_permissions系统功能:
这些是SQL Server 2005中的新的权限类型:
· CONTROL。 授予所有者想要的权限,这些权限可以有效地对这个对象授予所有定义的权限,并且所有对象在它的范围内,包括授予其它受权人任何权限的能力。CONTROL SERVER授予等价于sysadmin的权限。
· ALTER。授予权限来修改可得到的对象的任何属性,除了修改所属关系。固定地授予权限给相同范围内的ALTER、CREATE或 DROP 可得到的对象。例如,授予一个数据库上的ALTER权限,包括修改它的表。
· ALTER ANY <可得到的对象>。 授予权限以修改可得到的指定类型的对象。例如,授予ALTER ANY ASSEMBLY允许修改数据库中的任何.NET 集合,而在服务器级别授予ALTER ANY LOGIN 使得用户修改任何在服务器上的登陆。
· IMPERSONATE ON <登陆或用户>。 授予权限来模拟特定的用户或登陆。你在本篇文章的后面可以看到,这个权限对于为存储过程转换执行上下文是很必要的。你在一个批处理中进行模拟也需要这个权限。
· TAKE OWNERSHIP。 授予权限给受权人以使用可得到的所有权,使用ALTER AUTHORIZATION语句。
SQL Server 2008仍然使用类似的GRANT、DENY和REVOKE scheme来指派或拒绝给一个主体授予对一个可得到的对象的权限。现在ANT 语句涵盖了所有新的权限选项,例如授予的范围和是否主体可以授予这个权限给其它主体。SQL Server 不允许数据库交叉权限。为了授予这样的权限,你要在每一个数据库中创建一个复制的用户,并单独的给每一个数据库用户指派这个权限。
如同SQL Server 之前的版本一样,激活一个应用程序角色会在这个角色活动的期限内挂起其它的权限。然而,在SQL Server 2008和SQL Server 2005中,你具有卸载应用程序角色的能力。SQL Server 2000和之后版本的另一个不同之处是,当激活一个应用程序角色时,这个角色还会挂起任何服务器权限,包括public。例如,如果你授予VIEW ANY DEFINITION给public,应用程序不会受益于它。这是当在一个应用程序角色上下文中访问服务器级别的元数据时值得注意的。
注意 这个新的首选的应用程序角色选择将使用代码模块中的执行上下文。要获得更多的信息,请查看本文中的执行上下文一节。
授予一个特殊的权限可以传递其它暗含的权限。例如在一个schema 上的ALTER 权限暗含了更细粒度和较低级别的权限。图5显示了ALTER SCHEMA暗含的权限。
当你考虑可用的主体的数目和类型、服务器和一个典型的数据库中的可得到的对象的数目、可用的权限和隐藏的以及暗含的权限的数目时,“在SQL Server 2008中的细粒度权限是怎样的”就立刻清楚了。现在创建一个数据库要求更细致地分析它的安全需求和谨慎地控制在所有对象上的权限。然而,这个分析是很值得的,在SQL Server 2008中使用这些功能会使得数据库更安全。
4.4 元数据安全
细粒度权限scheme 的一个好处是SQL Server保护元数据和数据。在SQL Server 2005之前,一个用户对数据库的任何访问都会看到数据库中的所有对象的元数据,无论这个用户是否可以访问其中的数据或执行存储过程。
SQL Server 2008检查主体在数据库中具有的权限,并仅当这个主体是所有人或他具有这个对象的一些权限时才可以显示这个对象的元数据。还有一个VIEW DEFINITION 权限可以授予查看元数据信息的权限,它甚至不需要这个对象的其它权限。
这个保护扩展到因用户没有权限所做的访问或更新对象的操作所返回的错误信息。不只是承认确实有一个表叫做Address ,还给攻击者一个信息说她被跟踪了,SQL Server返回一个具有选择可能性的错误信息。例如,如果一个用户没有对数据库中的任何对象的权限,他试图删除Address表,那么SQL Server 会显示下面的错误信息:
在这种方式下,攻击者不能确定一个Address表是否真的存在。然而,调试这个问题的人仍然只需要探究有限的可能性。
4.5 SQL Server Agent代理
在SQL Server 2008中的授权模型的一个最好的例子就是SQL Server Agent。你可以定义许多常常与Windows登陆关联的凭证,链接到具有必要的权限的用户以执行一个或多个SQL Server Agent步骤。然后一个SQL Server Agent 代理会使用一个工作步骤链接这个凭证来提供必要的权限。
这为下面的最小权限的主体提供了一个细粒度的方法:授予一个工作步骤所需的权限,除此以外没有其它权限。你可以创建任何数目的代理,将它们的每一个同一个或多个SQL Server Agent子系统关联起来。这是对SQL Server 2000中的所有强大的代理帐户的完全约束,它使得用户可以在任何SQL Server Agent子系统中创建工作步骤。
注意 当你对一个SQL Server 2000服务器进行升级的时候,会创建一个单独的代理账户,所有的子系统会被分配到这个单独的代理账户上以便现有的工作可以继续运行。在升级之后,创建凭证和代理账户来实现一组更加安全的、更细粒度的代理来保护服务器资源。
图6显示了管理套件中的对象资源管理器和一列SQL Server Agent中可用的子系统。每一个子系统可以有与它关联的一个或多个代理,它们授予这个工作步骤所需的适当的权限。这个scheme的一个例外是 Transact-SQL子系统以模块所有者的权限来执行,这和在SQL Server 2000中是一样的。
在一个新安装的SQL Server 之上,只有System Administrator 角色具有维护SQL Server Agent 工作的权限,管理套件资源管理器中的管理面板只对sysadmins开放。SQL Server 2008具有一些其它的、你可以用来授予多级权限的角色。你可以将用户分配到SQLAgentUser、SQLAgentReaderRole或 SQLAgentOperator 角色,其中的每一个授予逐渐增长的权限级别来创建、管理和运行工作,或是MaintenanceUser 角色,它具有SQLAgentUser的所有的权限和创建维护计划的能力。
sysadmin 角色的成员当然可以在任何子系统中做任何他们想要做的。为了授权给任何其他的用户以使用子系统,要求至少创建一个代理帐户,它可以授权给一个或多个子系统。图7显示一个代理帐户MyProxy怎样被分配到多个主体上,这里是一个用户和一个角色。这个代理帐户使用一个凭证,这个凭证将它链接到一个帐户,通常是一个域帐户,它要具有操作系统执行子系统所要求的所有任务所必需的权限。每一个代理可以有一个或多个相关联的子系统,这些子系统授予主体以运行这些子系统的能力。
下面的代码显示了执行图7所示的scheme所必需的Transact-SQL代码。它一开始创建了一个凭证,一个提供了对具有执行子系统中想要的活动的权限的操作系统帐户的链接的数据库对象。然后它添加一个代理帐户——MyProxy,这只是一个用于凭证的友好名称。然后,它将这个代理分派到两个首要角色上,在这里是一个SQL Server登陆和一个定制角色。最后它将这个代理和四个SQL Server Agent子系统的每一个相关联。
SQL Server管理套件提供了对创建凭证和代理的充分支持,如图8所示。它创建了与之前的代码相同的代理。
一个代理不是操作系统中围绕安全的一个方式。如果和代理一起使用的凭证没有在Windows中的权限,例如写到网络上的一个目录中,那么代理也没有这个权限。你还可以使用一个代理来授予有限的执行权限给xp_cmdshell ,因为它是攻击者所喜爱的一个工具,一旦他们危及一个SQL Server计算机他们就能扩展他们在网络中的范围。这个代理提供了这个保护,因为即使主体具有在网络上的无限的权限,例如域管理员,但是通过代理执行的任何命令只具有凭证帐户所具有的有限的权限。
4.6 执行上下文
SQL Server 很久以来就支持所有权链接作为一个确保管理员和应用程序开发人员对访问数据库的入口检查其权限而不是对所有访问的对象的权限进行检查的概念。只要调用模块 (存储过程或函数)或者视图的用户具有对这个模块的执行权限,或者具有对视图的选择权限,并且这个模块或视图的所有人是访问对象的所有人(一个所有权链),那么就不会检查对基本对象具有的权限,而调用者会得到请求的数据。
如果所有权链接由于代码的所有者不拥有引用的对象的原因而被破坏了,那么SQL Server将对调用者的安全上下文检查权限。如果调用者具有访问这个对象的权限,那么SQL Server 返回数据。如果她没有,那么SQL Server 将报错。
所有权链接有一些局限性;它只适用于数据操作而不适用于动态SQL。进一步的,如果你穿过所有权限定访问对象,所有权链接就不可用。因此,这个预先的权限检查行为只能用于特定的情况。
SQL Server 2008具有使用一个执行上下文标识模块的能力,这样在模块中的语句就可以作为与调用用户相反的特殊用户来执行。这个方式,当调用用户仍然需要权限来执行模块时,SQL Server为模块内的语句对模块的执行上下文检查权限。你可以使用这个行动来克服所有权链接的一些缺点,因为它适用于模块内的所有语句。管理员如果想执行预先的权限检查的话可以使用执行上下文来完成这个工作。
现在当你定义用户定义的功能(除了在线的值为表的情况),存储过程和触发器时你可以使用EXECUTE AS 条件来指定SQL Server 使用哪个用户的权限来验证对由以下过程引用的对象和数据的访问:
SQL Server 提供了四个EXECUTE AS选项。
· EXECUTE AS CALLER 指定了在模块的调用者的安全上下文中执行的代码;没有发生身份模拟。调用者必须具有对所有引用的对象的访问权限。然而,SQL Server 只检查对所有权断链的权限,所以如果这个代码的所有者还拥有后台的对象,那么只会检查模块的执行权限。这是向后兼容性的默认执行上下文。
· EXECUTE AS 'user_name' 指定了代码执行在指定用户的安全上下文下。如果你不想依赖于所有权链那么这是一个很好的选择。相反,你创建一个具有必要权限的用户来允许这个代码和创建定制的权限集合。
· EXECUTE AS SELF 是一个缩写符号,用于指定要创建或修改这个模块的用户的安全上下文。SQL Server 在内部保存和这个模块相关联的实际的用户名称,而不是“SELF”。
· EXECUTE AS OWNER 指定这个安全上下文是模块执行时的模块当前所有者的安全上下文。如果这个模块没有所有者,那么使用所包含的schema的所有者的上下文。当你想能够改变这个模块的所有者而不改变模块本身的时候这是一个很好的选择。
只要用户上下文使用EXECUTE AS选项进行变更,那么模块的创建者或更改者必须具有对指定的用户的IMPERSONATE权限。你不能从数据库中删除指定的用户,除非你将所有模块的执行上下文更改为其它的用户。
4.7 用户/schema分离
SQL Server 2000没有schema的概念,而在ANSI SQL-99规范中将schema定义为一个数据库对象的集合,由形成了对象的一个单独的命名空间的一个单独的主体所有。Schema是数据库对象的一个容器,例如表、视图、存储过程、函数、类型和触发器。它在.NET框架中更多的是作为一个命名空间函数,而XML是一种组织对象的方式,以便数据库可以重用对象名称,例如允许dbo.Customer和Fred.Customer存在于一个单独的数据库中,并将对象分类到不同的所有者下面。
注意你将需要使用目录视图例如sys.database_sys.principals、sys.schemas, sys.objects等等。因为老的sysobjects系统表不支持schemas,因此不能支持U/S分离。此外,老的目录视图是不被支持的,所以它们在SQL Server的未来版本中将被删除。
图9的上面部分显示了SQL Server 2000中schemas是怎样工作的。当一个管理员在数据库中创建一个用户Alice 时,SQL Server 会自动地创建一个隐藏在用户Alice之后的schema Alice。如果Alice 登陆到一个运行SQL Server而他没有所有权的服务器上创建Table1,那么表的实际名称是Alice.Table1。Alice 创建的其它对象也是一样,例如Alice.StoredProcedure1和Alice.View1。如果Alice 是一个数据库所有人或者是sysadmin ,那么她创建的对象将是dbo schema的一部分。尽管我们习惯说dbo拥有对象,但是它其实是一回事。
在SQL Server 2000 中当你需要改变对象的所有权时就会遇到用户和schemas的统一问题,例如当Alice离开公司而Lucinda接替了Alice的工作。那么一个系统管理员需要将Alice所拥有的所有对象的所有权改变为Lucinda的。一个更大的问题是在Lucinda具有了表的所有权之后你需要将所有涉及到 Alice.Table1的Transact-SQL或客户端应用程序代码改变为Lucinda.Table1。这取决于Alice所拥有的对象的数目和有多少应用程序中内嵌了这个名字;这是一个很大的消耗。Microsoft很久以前就建议内置的dbo用户拥有所有的数据库对象来解决这些问题。更改一个数据库所有权比更改许多对象和客户端应用程序要容易得多。
注意 不要被SQL Server 2000的CREATE SCHEMA语句混淆。这只是一个创建特定用户所拥有的表和视图和授权的简便方法。你可以使用这个语句来命名一个schema的所有者但是不能命名这个 schema。因为要改变所有权的问题,SQL Server仍然不能将所有者链接到schema上。
要想知道在SQL Server中可用的权限的数目,你可以调用fn_builtin_permissions系统功能:
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-06_IvYDkrAkuwTI.jpg)
这些是SQL Server 2005中的新的权限类型:
· CONTROL。 授予所有者想要的权限,这些权限可以有效地对这个对象授予所有定义的权限,并且所有对象在它的范围内,包括授予其它受权人任何权限的能力。CONTROL SERVER授予等价于sysadmin的权限。
· ALTER。授予权限来修改可得到的对象的任何属性,除了修改所属关系。固定地授予权限给相同范围内的ALTER、CREATE或 DROP 可得到的对象。例如,授予一个数据库上的ALTER权限,包括修改它的表。
· ALTER ANY <可得到的对象>。 授予权限以修改可得到的指定类型的对象。例如,授予ALTER ANY ASSEMBLY允许修改数据库中的任何.NET 集合,而在服务器级别授予ALTER ANY LOGIN 使得用户修改任何在服务器上的登陆。
· IMPERSONATE ON <登陆或用户>。 授予权限来模拟特定的用户或登陆。你在本篇文章的后面可以看到,这个权限对于为存储过程转换执行上下文是很必要的。你在一个批处理中进行模拟也需要这个权限。
· TAKE OWNERSHIP。 授予权限给受权人以使用可得到的所有权,使用ALTER AUTHORIZATION语句。
SQL Server 2008仍然使用类似的GRANT、DENY和REVOKE scheme来指派或拒绝给一个主体授予对一个可得到的对象的权限。现在ANT 语句涵盖了所有新的权限选项,例如授予的范围和是否主体可以授予这个权限给其它主体。SQL Server 不允许数据库交叉权限。为了授予这样的权限,你要在每一个数据库中创建一个复制的用户,并单独的给每一个数据库用户指派这个权限。
如同SQL Server 之前的版本一样,激活一个应用程序角色会在这个角色活动的期限内挂起其它的权限。然而,在SQL Server 2008和SQL Server 2005中,你具有卸载应用程序角色的能力。SQL Server 2000和之后版本的另一个不同之处是,当激活一个应用程序角色时,这个角色还会挂起任何服务器权限,包括public。例如,如果你授予VIEW ANY DEFINITION给public,应用程序不会受益于它。这是当在一个应用程序角色上下文中访问服务器级别的元数据时值得注意的。
注意 这个新的首选的应用程序角色选择将使用代码模块中的执行上下文。要获得更多的信息,请查看本文中的执行上下文一节。
授予一个特殊的权限可以传递其它暗含的权限。例如在一个schema 上的ALTER 权限暗含了更细粒度和较低级别的权限。图5显示了ALTER SCHEMA暗含的权限。
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-16_1Wvv9LAE6cXp.jpg)
当你考虑可用的主体的数目和类型、服务器和一个典型的数据库中的可得到的对象的数目、可用的权限和隐藏的以及暗含的权限的数目时,“在SQL Server 2008中的细粒度权限是怎样的”就立刻清楚了。现在创建一个数据库要求更细致地分析它的安全需求和谨慎地控制在所有对象上的权限。然而,这个分析是很值得的,在SQL Server 2008中使用这些功能会使得数据库更安全。
4.4 元数据安全
细粒度权限scheme 的一个好处是SQL Server保护元数据和数据。在SQL Server 2005之前,一个用户对数据库的任何访问都会看到数据库中的所有对象的元数据,无论这个用户是否可以访问其中的数据或执行存储过程。
SQL Server 2008检查主体在数据库中具有的权限,并仅当这个主体是所有人或他具有这个对象的一些权限时才可以显示这个对象的元数据。还有一个VIEW DEFINITION 权限可以授予查看元数据信息的权限,它甚至不需要这个对象的其它权限。
这个保护扩展到因用户没有权限所做的访问或更新对象的操作所返回的错误信息。不只是承认确实有一个表叫做Address ,还给攻击者一个信息说她被跟踪了,SQL Server返回一个具有选择可能性的错误信息。例如,如果一个用户没有对数据库中的任何对象的权限,他试图删除Address表,那么SQL Server 会显示下面的错误信息:
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-24_vJeP18sZojwh.jpg)
在这种方式下,攻击者不能确定一个Address表是否真的存在。然而,调试这个问题的人仍然只需要探究有限的可能性。
4.5 SQL Server Agent代理
在SQL Server 2008中的授权模型的一个最好的例子就是SQL Server Agent。你可以定义许多常常与Windows登陆关联的凭证,链接到具有必要的权限的用户以执行一个或多个SQL Server Agent步骤。然后一个SQL Server Agent 代理会使用一个工作步骤链接这个凭证来提供必要的权限。
这为下面的最小权限的主体提供了一个细粒度的方法:授予一个工作步骤所需的权限,除此以外没有其它权限。你可以创建任何数目的代理,将它们的每一个同一个或多个SQL Server Agent子系统关联起来。这是对SQL Server 2000中的所有强大的代理帐户的完全约束,它使得用户可以在任何SQL Server Agent子系统中创建工作步骤。
注意 当你对一个SQL Server 2000服务器进行升级的时候,会创建一个单独的代理账户,所有的子系统会被分配到这个单独的代理账户上以便现有的工作可以继续运行。在升级之后,创建凭证和代理账户来实现一组更加安全的、更细粒度的代理来保护服务器资源。
图6显示了管理套件中的对象资源管理器和一列SQL Server Agent中可用的子系统。每一个子系统可以有与它关联的一个或多个代理,它们授予这个工作步骤所需的适当的权限。这个scheme的一个例外是 Transact-SQL子系统以模块所有者的权限来执行,这和在SQL Server 2000中是一样的。
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-35_I7UEZZJzPj04.jpg)
在一个新安装的SQL Server 之上,只有System Administrator 角色具有维护SQL Server Agent 工作的权限,管理套件资源管理器中的管理面板只对sysadmins开放。SQL Server 2008具有一些其它的、你可以用来授予多级权限的角色。你可以将用户分配到SQLAgentUser、SQLAgentReaderRole或 SQLAgentOperator 角色,其中的每一个授予逐渐增长的权限级别来创建、管理和运行工作,或是MaintenanceUser 角色,它具有SQLAgentUser的所有的权限和创建维护计划的能力。
sysadmin 角色的成员当然可以在任何子系统中做任何他们想要做的。为了授权给任何其他的用户以使用子系统,要求至少创建一个代理帐户,它可以授权给一个或多个子系统。图7显示一个代理帐户MyProxy怎样被分配到多个主体上,这里是一个用户和一个角色。这个代理帐户使用一个凭证,这个凭证将它链接到一个帐户,通常是一个域帐户,它要具有操作系统执行子系统所要求的所有任务所必需的权限。每一个代理可以有一个或多个相关联的子系统,这些子系统授予主体以运行这些子系统的能力。
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-41_LhbIF85MPBMs.jpg)
下面的代码显示了执行图7所示的scheme所必需的Transact-SQL代码。它一开始创建了一个凭证,一个提供了对具有执行子系统中想要的活动的权限的操作系统帐户的链接的数据库对象。然后它添加一个代理帐户——MyProxy,这只是一个用于凭证的友好名称。然后,它将这个代理分派到两个首要角色上,在这里是一个SQL Server登陆和一个定制角色。最后它将这个代理和四个SQL Server Agent子系统的每一个相关联。
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-49_qSmi2liYgRJ5.jpg)
SQL Server管理套件提供了对创建凭证和代理的充分支持,如图8所示。它创建了与之前的代码相同的代理。
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-27-57_epIcf8YZfv5P.jpg)
一个代理不是操作系统中围绕安全的一个方式。如果和代理一起使用的凭证没有在Windows中的权限,例如写到网络上的一个目录中,那么代理也没有这个权限。你还可以使用一个代理来授予有限的执行权限给xp_cmdshell ,因为它是攻击者所喜爱的一个工具,一旦他们危及一个SQL Server计算机他们就能扩展他们在网络中的范围。这个代理提供了这个保护,因为即使主体具有在网络上的无限的权限,例如域管理员,但是通过代理执行的任何命令只具有凭证帐户所具有的有限的权限。
4.6 执行上下文
SQL Server 很久以来就支持所有权链接作为一个确保管理员和应用程序开发人员对访问数据库的入口检查其权限而不是对所有访问的对象的权限进行检查的概念。只要调用模块 (存储过程或函数)或者视图的用户具有对这个模块的执行权限,或者具有对视图的选择权限,并且这个模块或视图的所有人是访问对象的所有人(一个所有权链),那么就不会检查对基本对象具有的权限,而调用者会得到请求的数据。
如果所有权链接由于代码的所有者不拥有引用的对象的原因而被破坏了,那么SQL Server将对调用者的安全上下文检查权限。如果调用者具有访问这个对象的权限,那么SQL Server 返回数据。如果她没有,那么SQL Server 将报错。
所有权链接有一些局限性;它只适用于数据操作而不适用于动态SQL。进一步的,如果你穿过所有权限定访问对象,所有权链接就不可用。因此,这个预先的权限检查行为只能用于特定的情况。
SQL Server 2008具有使用一个执行上下文标识模块的能力,这样在模块中的语句就可以作为与调用用户相反的特殊用户来执行。这个方式,当调用用户仍然需要权限来执行模块时,SQL Server为模块内的语句对模块的执行上下文检查权限。你可以使用这个行动来克服所有权链接的一些缺点,因为它适用于模块内的所有语句。管理员如果想执行预先的权限检查的话可以使用执行上下文来完成这个工作。
现在当你定义用户定义的功能(除了在线的值为表的情况),存储过程和触发器时你可以使用EXECUTE AS 条件来指定SQL Server 使用哪个用户的权限来验证对由以下过程引用的对象和数据的访问:
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-28-07_rbPf9En9OePg.jpg)
SQL Server 提供了四个EXECUTE AS选项。
· EXECUTE AS CALLER 指定了在模块的调用者的安全上下文中执行的代码;没有发生身份模拟。调用者必须具有对所有引用的对象的访问权限。然而,SQL Server 只检查对所有权断链的权限,所以如果这个代码的所有者还拥有后台的对象,那么只会检查模块的执行权限。这是向后兼容性的默认执行上下文。
· EXECUTE AS 'user_name' 指定了代码执行在指定用户的安全上下文下。如果你不想依赖于所有权链那么这是一个很好的选择。相反,你创建一个具有必要权限的用户来允许这个代码和创建定制的权限集合。
· EXECUTE AS SELF 是一个缩写符号,用于指定要创建或修改这个模块的用户的安全上下文。SQL Server 在内部保存和这个模块相关联的实际的用户名称,而不是“SELF”。
· EXECUTE AS OWNER 指定这个安全上下文是模块执行时的模块当前所有者的安全上下文。如果这个模块没有所有者,那么使用所包含的schema的所有者的上下文。当你想能够改变这个模块的所有者而不改变模块本身的时候这是一个很好的选择。
只要用户上下文使用EXECUTE AS选项进行变更,那么模块的创建者或更改者必须具有对指定的用户的IMPERSONATE权限。你不能从数据库中删除指定的用户,除非你将所有模块的执行上下文更改为其它的用户。
4.7 用户/schema分离
SQL Server 2000没有schema的概念,而在ANSI SQL-99规范中将schema定义为一个数据库对象的集合,由形成了对象的一个单独的命名空间的一个单独的主体所有。Schema是数据库对象的一个容器,例如表、视图、存储过程、函数、类型和触发器。它在.NET框架中更多的是作为一个命名空间函数,而XML是一种组织对象的方式,以便数据库可以重用对象名称,例如允许dbo.Customer和Fred.Customer存在于一个单独的数据库中,并将对象分类到不同的所有者下面。
注意你将需要使用目录视图例如sys.database_sys.principals、sys.schemas, sys.objects等等。因为老的sysobjects系统表不支持schemas,因此不能支持U/S分离。此外,老的目录视图是不被支持的,所以它们在SQL Server的未来版本中将被删除。
图9的上面部分显示了SQL Server 2000中schemas是怎样工作的。当一个管理员在数据库中创建一个用户Alice 时,SQL Server 会自动地创建一个隐藏在用户Alice之后的schema Alice。如果Alice 登陆到一个运行SQL Server而他没有所有权的服务器上创建Table1,那么表的实际名称是Alice.Table1。Alice 创建的其它对象也是一样,例如Alice.StoredProcedure1和Alice.View1。如果Alice 是一个数据库所有人或者是sysadmin ,那么她创建的对象将是dbo schema的一部分。尽管我们习惯说dbo拥有对象,但是它其实是一回事。
![](http://img2.51cto.com/attachments/month_0801/2008-01-30_14-28-17_BWre4dXRw4wE.jpg)
在SQL Server 2000 中当你需要改变对象的所有权时就会遇到用户和schemas的统一问题,例如当Alice离开公司而Lucinda接替了Alice的工作。那么一个系统管理员需要将Alice所拥有的所有对象的所有权改变为Lucinda的。一个更大的问题是在Lucinda具有了表的所有权之后你需要将所有涉及到 Alice.Table1的Transact-SQL或客户端应用程序代码改变为Lucinda.Table1。这取决于Alice所拥有的对象的数目和有多少应用程序中内嵌了这个名字;这是一个很大的消耗。Microsoft很久以前就建议内置的dbo用户拥有所有的数据库对象来解决这些问题。更改一个数据库所有权比更改许多对象和客户端应用程序要容易得多。
注意 不要被SQL Server 2000的CREATE SCHEMA语句混淆。这只是一个创建特定用户所拥有的表和视图和授权的简便方法。你可以使用这个语句来命名一个schema的所有者但是不能命名这个 schema。因为要改变所有权的问题,SQL Server仍然不能将所有者链接到schema上。