SQLServer 2012 包含数据库(Contained Databases)

SQLServer 2012 包含数据库(Contained Databases),第1张

概述“包含数据库”是独立于其他数据库以及承载数据库的 SQL Server 实例的一种数据库。 SQL Server 2012 以 4 种方法帮助用户使其数据库独立于实例。 ▶很多用于描述数据库的元数据都在该数据库中维护。 (除此之外或代替在 master 数据库中维护元数据。) ▶使用相同的排序规则定义所有元数据。 ▶数据库可执行用户身份验证,因此减少了对 SQL Server 实例的登录名的数据库

“包含数据库”是独立于其他数据库以及承载数据库的 sql Server 实例的一种数据库。 sql Server 2012 以 4 种方法帮助用户使其数据库独立于实例。


▶很多用于描述数据库的元数据都在该数据库中维护。 (除此之外或代替在 master 数据库中维护元数据。)
▶使用相同的排序规则定义所有元数据。
▶数据库可执行用户身份验证,因此减少了对 sql Server 实例的登录名的数据库依赖关系。
▶sql Server 环境(DMV、XEvent 等)报告并可以执行包含信息。


相关概念:(更多参考:包含数据库)
数据库边界:数据库和 sql Server 实例之间的边界。 数据库和其他数据库之间的边界。
包含:完全在数据库边界中存在的元素。
非包含:跨数据库边界的元素。
非包含数据库:具有设置为 NONE 的包含的数据库。 版本早于 sql Server 2012 的所有数据库均属于非包含数据库。 默认情况下,所有 sql Server 2012 数据库的包含都设置为 NONE。
部分包含数据库:部分包含数据库是一种包含数据库,可允许存在跨越数据库边界的某些功能。 sql Server 包括确定何时跨越包含边界的功能。
包含的用户:包含数据库有两种用户类型。


以下测试包含数据库中的 对象、用户、排序规则是怎么独立的!


【初始环境】

--创建数据库 DROP DATABASE DemoDatabaseUSE [master]GOCREATE DATABASE DemoDatabaseColLATE sql_latin1_General_CP1_CI_ASGO--创建登录账户和数据库用户[UserA]USE [master]GOCREATE LOGIN [UserA] WITH PASSWORD=N'UserA',DEFAulT_DATABASE=[master],CHECK_EXPIRATION=OFF,CHECK_POliCY=OFFGOUSE [DemoDatabase]GOCREATE USER [UserA] FOR LOGIN [UserA]GOALTER RolE [db_owner] ADD MEMBER [UserA]GO--只创建登录账户[UserB]USE [master]GOCREATE LOGIN [UserB] WITH PASSWORD=N'UserB',CHECK_POliCY=OFFGO--创建windows用户和sqlserver登录账户[UserB]CREATE LOGIN [KK-PC\windowsUser] FROM windows WITH DEFAulT_DATABASE=[master]GO--先在数据库创建表USE [DemoDatabase]GOSELECT * INTO [Demotable] FROM sys.sysobjectsGOCREATE VIEW [VDemotable]AS SELECT * FROM [DemoDatabase].[DBO].[Demotable]GO

【将数据库 [DemoDatabase] 设置为部分包含数据库】

USE [master]GOEXEC sys.sp_configure N'show advanced',N'1';  GORECONfigURE WITH OVERRIDE;  GOEXEC sys.sp_configure N'contained database authentication',N'1';GORECONfigURE WITH OVERRIDE;GOALTER DATABASE [DemoDatabase] SET CONTAINMENT = PARTIAL WITH NO_WAITGO



【创建独立的数据库用户】

这里有四种登录用户,就测试四种情况(不包括加密用户)



【一】创建有密码的数据库用户(不需要创建登录账号)

--【一】创建有密码的数据库用户(不需要创建登录账号)USE [DemoDatabase]GOCREATE USER [UserC] WITH PASSWORD=N'UserC',DEFAulT_LANGUAGE=[English],DEFAulT_SCHEMA=[dbo]	GOALTER RolE [db_owner] ADD MEMBER [UserC]GO
连接数据库:



可以看到,当数据库的用户密码都包含在数据库中时,就不需要外部登录账号做映射了,直接可以访问数据库!切只能访问数据库中的资源,更好地控制了权限。


【二】从登录账号中创建数据库用户,与以前的添加一样:

--【二】从登录账号中创建数据库用户,与以前的添加一样。USE [DemoDatabase]GOCREATE USER [UserB] FOR LOGIN [UserB] WITH DEFAulT_SCHEMA=[dbo]GOALTER RolE [db_owner] ADD MEMBER [UserB]GO
该用户 [UserB] 需要登录账号做映射,属于边界外的对象。这种情况与非包含的数据库一样。

【三】从window创建数据库用户(这种添加用户的情况和上一种一样)

--【三】从window创建数据库用户(这种添加用户的情况和上一种一样)USE [DemoDatabase]GOCREATE USER [KK-PC\windowsUser] FOR LOGIN [KK-PC\windowsUser] WITH DEFAulT_LANGUAGE=[English],DEFAulT_SCHEMA=[dbo]	GOALTER RolE [db_owner] ADD MEMBER [KK-PC\windowsUser]GO

【四】添加无密码的数据库用户(与以前版本一样,因为特殊顺便说明这种情况用法吧)

--【四】添加无密码的数据库用户(与以前版本一样,因为特殊顺便说明这种情况用法吧)USE [DemoDatabase]GOCREATE USER [UserD] WITHOUT LOGIN WITH DEFAulT_SCHEMA=[dbo]	GOALTER RolE [db_owner] ADD MEMBER [UserD]GO--用windows账号测试,先回收其权限ALTER RolE [db_owner] DROP MEMBER [KK-PC\windowsUser]GO--使用 windows 账号[KK-PC\windowsUser]登录数据库并查询表USE [DemoDatabase]GOSELECT * FROM [dbo].[Demotable]GO

错误,并没有权限使用表



--回到管理员窗口,授予登录账号[KK-PC\windowsUser]使用数据库用户[UserD]的凭据USE [DemoDatabase]GOGRANT IMPERSONATE ON USER::[UserD] TO [KK-PC\windowsUser];GO 

--回到windows账号[KK-PC\windowsUser]的登录界面,切换用户执行语句!USE [DemoDatabase]GOEXECUTE AS USER = 'UserD' ;GOSELECT USER_name()SELECT * FROM [dbo].[Demotable]GOREVERT ;GO



结果可以查询了!数据库用户[UserD]虽然没有登录账号映射,但是可以授权给其他登录账号使用。


以上4种情况,主要是第一种才体现出了包含数据库的特性。



【相关查询】

USE [DemoDatabase]GO--显示数据库中使用的任何非包含对象SELECT * FROM sys.dm_db_uncontained_entitIEsSELECT * FROM sys.sql_modules--边界外的表等对象SELECT t1.name,t1.type,t0.*FROM sys.dm_db_uncontained_entitIEs t0 inner join sys.objects t1 on t0.major_ID=t1.object_ID and t0.class=1--边界外的用户SELECT t1.name,t0.*FROM sys.dm_db_uncontained_entitIEs t0 inner join sys.database_principals t1 on t0.major_ID=t1.principal_ID and t0.class=4


【将边界外的对象更改为边界内对象】

--对于视图,将引用的数据库名称去掉USE [DemoDatabase]GOALTER VIEW [VDemotable]AS SELECT * FROM [DBO].[Demotable]GO--对于用户(存在登录账户和数据库用户),禁用登录账号并中断映射。USE [DemoDatabase]GOEXEC sp_migrate_user_to_contained@username = N'UserA',@rename = N'keep_name',@disable_login = N'disable_login'  GOEXEC sp_migrate_user_to_contained@username = N'UserB',@disable_login = N'disable_login'  GO



【排序规则问题】

查看实例和数据库的排序规则,现在是不一样的。



USE [DemoDatabase]GO--	DROP table T1,#T2CREATE table T1 (T1_txt nvarchar(max)) ;GOCREATE table #T2 (T2_txt nvarchar(max));GOSELECT T1_txt FROM T1UNION ALLSELECT T2_txt FROM #T2SELECT T1_txt,T2_txt FROM T1 JOIN #T2 ON T1.T1_txt = #T2.T2_txt ;

执行结果在包含数据库中并没有出错!现在在非包含数据库中执行,会怎样呢??


USE [AdventureWorks2012]GO--	DROP table T1,T2_txt FROM T1 JOIN #T2 ON T1.T1_txt = #T2.T2_txt ;

Msg 451,Level 16,State 1,line 1
Cannot resolve collation conflict between "Chinese_PRC_CI_AS" and "sql_latin1_General_CP1_CI_AS" in UNION ALL operator occurring in SELECT statement column 1.

Msg 468,State 9,line 1
Cannot resolve the collation conflict between "Chinese_PRC_CI_AS" and "sql_latin1_General_CP1_CI_AS" in the equal to operation.


结果出错!因排序规则不同导致错误!默认情况下,数据库排序规则等同于 model 数据库排序规则。而临时数据库 tempdb 默认为实例的排序规则。由于包含数据库的设计目标是让自身实现独立,因此必须切断它们对实例和 tempdb 排序规则的依赖。 为此,包含数据库引入了目录排序规则的概念。 目录排序规则适用于系统元数据和临时对象.

--当然也可以使用 ColLATE 指定排序规则来兼容。USE [AdventureWorks2012]GOSELECT T1_txt ColLATE Chinese_PRC_CI_AS FROM T1 UNION ALLSELECT T2_txt FROM #T2SELECT T1_txt,T2_txt FROM T1 JOIN #T2 ON T1.T1_txt ColLATE Chinese_PRC_CI_AS = #T2.T2_txt ;



更多参考:

包含数据库: https://msdn.microsoft.com/zh-cn/library/ff929071(SQL.110).aspx
包含数据库的排序规则: https://msdn.microsoft.com/zh-cn/library/ff929080(v=sql.110).aspx
sys.dm_db_uncontained_entities: https://msdn.microsoft.com/zh-cn/library/ff929336(v=sql.110).aspx

总结

以上是内存溢出为你收集整理的SQLServer 2012 包含数据库(Contained Databases)全部内容,希望文章能够帮你解决SQLServer 2012 包含数据库(Contained Databases)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1168853.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存