简介

  在数据库中,我们除了存储数据外,还存储了大量的元数据。它们主要的作用就是描述数据库怎么建立、配置、以及各种对象的属性等。本篇简单介绍如何使用和查询元数据,如何更有效的管理SQLServer 数据库。

  对一些有经验的数据库开发和管理人员而言,元数据是非常有价值的。下面我会介绍一下简单的原理,然后尽量用代码的方式直接说明,毕竟“talk is cheap show me the code ”。

什么是动态在线目录?

  每一个关系型数据库系统,比如SQL Server 一定要提供关于它的结构的信息,这些信息往往需要通过sql语法来查询。通常这些信息被保存在指定数据表的结构中。这意味着数据库中有两种不同的表:一是用户自定义的表和系统表或者视图(包含元数据)。从SQL Server 2005开始,只有视图可以查询了,不能直接看到数据表了。

系统视图

这种系统表或者视图的结合通常参考关系型数据库理论的文献叫做作为系统目录或者数据字典。

在数据库内部,有一些系统表一直追踪数据库中发生的每一件事情。系统表存储像表、活动、列、索引等事情。这些完全符合Edgar Codd 的关系型数据库试试的十三条准则直译。这个准则就是定义动态在线目录,它就是“关于数据的数据”,也叫作元数据。

Edgar Codd  准则4, 描述如下:

‘The database description is represented at the logical level in the same way as ordinary data, so that authorized users can apply the same relational language to its interrogation as they apply to the regular data.’

翻译:像普通数据一样,在逻辑层的数据表达了对数据库的描述,以便于授权用户能应用相同的SQL语言来查询元数据,就如同查询常规数据一样。

在SQL Server中,可以通过系统视图或者架构视图直接访问动态在线目录,方便用户更为快捷的开发和管理数据库。

如何获得以上信息?

因为我们不能直接访问,需要使用视图和函数来看这些信息。只能看到你权限内的数据。有更好的方法在用户数据库中使用数据定义语言(DDL),这些DDL语句包括CREATE, DROP, ALTER, GRANT, DENY, REVOKE 和sp_rename statements 等。总有一种方法可以使用DDL来修改视图中的任何信息,即使并不总是显而易见的。

关系型数据库使用动态的系统视图中的数据描述数据库,但是目前还有没有标准化。但是有一个包含在每个数据库内的架构可以读取这些信息:就是Information Schema

不走运的是,这个架构不足以提供足够信息,这意味着我们需要使用SQL Server 系统数据库的视图和函数来补充信息。接下来需要解释一些术语和技术,我会尽可能少的细节足以让大家轻松地理解这些示例

如图所示,如何访问元数据,及其接口

 

系统视图

Information Schema

这个架构是一套视图,视图中是当前数据库的信息。每一个数据库中都有这个架构,只能看到当前数据库的对象信息。可以直接访问这些架构的数据在主要的关系型数据中。其中架构视图不包含数据库部署信息。

对于不同的关系型数据库之间的处理工作这个架构尤其重要。它们非常适合日常工作,例如在访问钱检查是否存在,但是如果需要详细报告则会受到限制。他们还使用一种稍有不同的标准命名法:例如,数据库被称为目录,用户定义的数据类型被称为“domain”。

之前看到MSDN上有人警告说不要使用INFORMATION_SCHEMA视图来确认对象架构,我理解是因为SQL Server允许在不同的架构中有相同的表名字,因此当只有表名称的时候会有混淆。所以我认为尽管放心使用就好了。

兼容性视图

兼容性视图是维护元数据的视图,在SQL Server 2005之前是有系统表支持的,并且只向后兼容。只在2005之后的版本支持对于某些系统表的查询,例如分区表等,只有部分元数据或者特性是对用户可见的。对于带有很多用户、群组、角色或者2000版本数据类型的数据库而言,使用兼容性视图是有潜在风险的,因为视图中有的列存储了用户的ID或者类型ID,可能会返回NULL或者触发溢出。

目录视图

目录视图提供了关于数据库架构的信息。它们也被数据库引擎自己本身使用,尤其在查询优化环节。因此这些视图需要更高效的方式来获取元数据。除了复制、备份、数据库维护计划或SQL Server代理目录数据之外,所有元数据都通过这些编目视图公开。

这些视图用一种相当特殊的方式排列,SQL Server对象的共有信息都保存在sys.objects里面。有许多派生视图,比如外键、约束、服务队列、表、视图和过程,这些视图用特定于被编目的对象类型的信息来补充一般的对象信息

并非SQL Server元数据中的所有内容都是对象。例如,一个列、索引或分布统计信息不是对象。一些如主键约束或扩展属性有一个奇怪的两面性,因为它们被被当做为一个对象,当被强制键索引的实例化时,它就不是一个对象。有些对象(主要是约束)与另一种类型的对象具有父/子关系;父即表。

数据层应用程序视图

数据层应用程序视图被用于访问注册服务器信息。特殊版本的服务器和信息用来检查这些版本是否漂移。这是一种作为容易的检查当前注册数据库版本的方式,直接用T-SQL查询。

动态管理视图和功能(DMVs)

DMV一般用来调优,诊断问题和监控数据库服务器状态。最重要的作用就是提供了一种方式来查询数据库的使用信息。例如,不仅查询到索引,而且可以查询到使用量的排序和耗时等。

元数据function

还有很多元数据函数,如object_name()或col_name(),它们提供关于当前数据库中的模式作用域对象的信息。通过避免在元数据表达式中进行显式连接,它们提供了获取信息的捷径,因此,当与编目视图一起使用时,它们可以帮助您更快地获取关于元数据的信息。

目录存储过程

有许多存储过程的主要功能是为SQL Server的ODBC驱动程序提供元数据信息。当您建立ODBC连接时,该信息作为数据对象的集合。但是,这些信息通常是可用的,并且可以像任何其他存储过程一样从SQL中使用。它们通常被认为不如目录视图有用,因为存储过程返回的结果必须使用INSERT插入一个表或者表变量中,需要使用INSERT ... EXECUTE 语法。

为什么元数据视图和功能很重要?

元数据视图和函数允许您搜索元数据,提供对数据库报告和总结,找出谁有权限查看或改变什么数据,让你减少重复输入,让几乎所有隐藏在SQL Server Management Studio的信息可查询,使部署脚本更安全,更可靠,找出最近的改变或创建,快速处理一些函数或过程,确定已注册数据库的版本,审计用于编码实践的数据库代码,发现重复索引并且允许减少低效的点击操作。当与其他SQL Server工具(如默认跟踪和动态管理对象)结合使用时,使用强大的SQL脚本用于开发和管理数据库是相当快速的。

元数据视图和函数允许执行几乎不可能执行的操作,例如查找依赖于指定的CLR用户定义类型或别名类型的参数。

我是如何逐渐使用的?

学习使用元数据视图和函数的第一阶段是收集从各种著名的数据源(如SQL Server Central)中使用它们的查询。可以在MSDN上查询到。使用记录工具保存这些查询。如果它是一个用来保存注释或片段的工具,可以让您在任何地方轻松地获取查询,那么它将会有所帮助。一段时间后,就可以根据使用需要对这些查询稍作修改。然后,不需要在object browser窗格中搜索表列表,您很快就可以从集合中获取适当的查询,执行它,并快速获取信息。

比较有用的查询实例

下面我会展示的例子都已经在2008和2012 两个版本中测试。当然只用到了各自版本的最后一个版本更新后的数据库。

下图中展示了所有继承sys.objects列的视图。这意味着它们除了拥有这些列以外,还有列的对应类型。这是视图所有的信息比如create_date也都来自sys.objects

 

要列出数据库中的所有视图(存储过程和外键),只需执行以下操作 …

SELECT  object_schema_name(object_id)+'.'+name FROM sys.views;

 SELECT  object_schema_name(object_id)+'.'+name FROM sys.procedures;

SELECT name AS Foreign_key,object_schema_name(parent_object_ID)+'.'+object_name(parent_object_ID) AS parent,

object_schema_name(referenced_object_ID)+'.'+object_name(referenced_object_ID) AS referenced


FROM sys.foreign_keys;


对于所有其他的,您需要使用一个系统函数来过滤您想要的对象。下面的代码提供了一些有用的示例。因为我们只获取对象的名称,所以使用sys.objects,它具有所有数据库对象共有的基本信息的视图。如果我们需要特定于特定类型对象的信息,比如主键是否具有系统生成的名称,那么您就必须为该特定类型的对象使用视图。

/* The Tables */
--数据库中的所有用户表
SELECT
ob.name AS User_Table, Coalesce(ep.value, '') AS documentation
FROM sys.objects AS ob
LEFT OUTER JOIN sys.extended_properties AS ep
ON ep.major_id = ob.object_id
AND ep.class =
AND ep.minor_id =
WHERE ObjectProperty(ob.object_id, 'IsUserTable') =
/* The Views */
--视图
SELECT ob.name AS ViewName, Coalesce(ep.value, '') AS documentation
FROM sys.objects ob LEFT OUTER JOIN sys.extended_properties AS ep
ON ep.major_id = ob.object_id
AND ep.class = 1
AND ep.minor_id = 0
WHERE objectproperty(ob.object_id,'IsView')= 1 /* The Check Constraints */
--Check约束
SELECT
objects.name AS Name_of_Check_Constraint,
Object_Schema_Name(objects.parent_object_id) + '.' + Object_Name(objects.parent_object_id) AS parent,
Coalesce(ep.value,'') AS documentation
FROM sys.objects
LEFT OUTER JOIN sys.extended_properties AS ep
ON ep.major_id = objects.object_id AND ep.class=1
AND ep.name='MS_Description'--microsoft 公约
WHERE ObjectProperty(objects.object_id, 'IsCheckCnst') = 1 /* The Constraints */
SELECT
--约束
objects.name AS Name_of_Constraint, --see all constraints and parent table
Lower(Replace(type_desc,'_',' ')),--the type of constraint
Object_Schema_Name(objects.parent_object_id) + '.' + Object_Name(objects.parent_object_id) AS parent,
Coalesce(ep.value, '') AS documentation
FROM sys.objects
LEFT OUTER JOIN sys.extended_properties AS ep
ON ep.major_id = objects.object_id
AND ep.class = 1
AND ep.name = 'MS_Description'
WHERE ObjectProperty(objects.object_id, 'IsConstraint') = 1; /* The Defaults */
--默认
SELECT
objects.name,
Coalesce(ep.value, '') AS documentation
FROM sys.objects
LEFT OUTER JOIN sys.extended_properties AS ep
ON ep.major_id = objects.object_id
AND ep.class = 1
AND ep.name = 'MS_Description'
WHERE ObjectProperty(objects.object_id, 'IsDefault') = 1; /* The Default Constraints */
--数据库及其父表中的所有默认约束
SELECT objects.name AS Name_of_Default_Constraint,--see all Default constraints and parent table
Coalesce(ep.value,'') AS documentation,
object_schema_name(objects.parent_object_id)+'.'+object_name(objects.parent_object_id) AS parent,
Coalesce(EP_parent.value,'') AS documentation
FROM sys.objects
LEFT OUTER JOIN sys.extended_properties AS ep
ON ep.major_id = objects.object_id
AND ep.class = 1
AND ep.name = 'MS_Description' --the microsoft convention
LEFT OUTER JOIN sys.extended_properties AS EP_parent
ON ep.major_id = objects.parent_object_id
AND ep.name = 'MS_Description' --the microsoft convention
WHERE objectproperty(objects.object_id,'IsDefaultCnst')= 1; /* The Executables */
--数据库中的所有可执行文件(过程、函数等)
SELECT
oe.name AS Name_Of_Executable,
Replace(Lower(oe.type_desc), '_', ' ') AS Type_Of_Executable,
Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS oe
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = oe.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(oe.object_id, 'IsExecuted') = 1; /* The Extended Stored Procedures */
--数据库中的所有扩展存储过程
SELECT
oep.name AS Name_of_Extended_Procedure, Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS oep
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = oep.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(oep.object_id, 'IsExtendedProc') = 1; /* The Inline Functions */
--数据库中的所有内联函数
SELECT ilf.name AS Inline_function,
Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS ilf
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = ilf.object_id
AND EP.name = 'MS_Description'
WHERE objectproperty(ilf.object_id,'IsInlineFunction')= 1; /* The Primary Keys */
--数据库中的所有主键及其父表
SELECT
pk.name AS Primary_key,
Object_Schema_Name(pk.parent_object_id) + '.' + Object_Name(pk.parent_object_id) AS parent,
Coalesce(EP.value, '') AS KeyDoc, Coalesce(EPParent.value, '') AS TableDoc
FROM sys.objects AS pk
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = pk.object_id
AND EP.name = 'MS_Description'
LEFT OUTER JOIN sys.extended_properties AS EPParent
ON EPParent.major_id = pk.parent_object_id
AND EPParent.minor_id = 0
AND EPParent.name = 'MS_Description'
WHERE ObjectProperty(pk.object_id, 'IsPrimaryKey') = 1; /* The Stored Procedures */
--数据库中的所有存储过程
SELECT
sp.name AS Stored_procedure, Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS sp
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = sp.object_id
AND EP.minor_id = 0
AND EP.name = 'MS_Description'
WHERE ObjectProperty(sp.object_id, 'IsProcedure') = 1; /* The Queues */
--数据库中的所有队列
SELECT
q.name AS QueueName, Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS q
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = q.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(q.object_id, 'IsQueue') = 1; /* The Rules */
--数据库中的所有旧式规则
SELECT
ru.name AS RuleName, --old-fashioned sybase-style rule
Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS ru
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = ru.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(ru.object_id, 'IsRule') = 1; /* The Scalar Functions */
--数据库中的所有标量函数。
SELECT
sf.name AS Scalar_function, Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS sf
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = sf.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(sf.object_id, 'IsScalarFunction') = 1; /* The System Tables */
--据库中的所有系统表
SELECT
st.name AS System_table, Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS st
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = st.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(st.object_id, 'IsSystemTable') = 1; --数据库中的所有表,包括系统表
SELECT
at.name AS TableName,
Lower(Replace(type_desc,'_',' ')),--约束的类型
Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS at
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = at.object_id
AND EP.name = 'MS_Description'
WHERE ObjectProperty(at.object_id, 'IsTable') = 1; /* The TVFs*/
--数据库中的所有表值函数
SELECT
tvf.name AS Table_Valued_Function, Coalesce(EP.value, '') AS Documentation
FROM sys.objects AS tvf
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = tvf.object_id
AND EP.name = 'MS_Description' --the microsoft convention
WHERE ObjectProperty(tvf.object_id, 'IsTableFunction') = 1; --数据库及其所有触发器。
SELECT
tr.name AS TriggerName,
Object_Schema_Name(tr.parent_object_id) + '.' + Object_Name(tr.parent_object_id) AS parent,
Coalesce(EP.value, '') AS TriggerDoc, Coalesce(EPParent.value, '') AS TableDoc
FROM sys.objects AS tr
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = tr.object_id
AND EP.name = 'MS_Description'
LEFT OUTER JOIN sys.extended_properties AS EPParent
ON EPParent.major_id = tr.parent_object_id
AND EPParent.minor_id = 0
AND EPParent.name = 'MS_Description'
WHERE ObjectProperty(tr.object_id, 'IsTrigger') = 1; /* The Unique Constraints */
--数据库及其父表中的所有惟一约束
SELECT uc.name AS Unique_constraint,--所有唯一的约束
object_schema_name(uc.parent_object_id)+'.'+object_name(uc.parent_object_id) AS parent,
Coalesce(EP.value, '') AS ConstraintDoc, Coalesce(EPParent.value, '') AS TableDoc
FROM sys.objects AS uc
LEFT OUTER JOIN sys.extended_properties AS EP
ON EP.major_id = uc.object_id
AND EP.name = 'MS_Description'
LEFT OUTER JOIN sys.extended_properties AS EPParent
ON EPParent.major_id = uc.parent_object_id
AND EPParent.minor_id = 0
AND EPParent.name = 'MS_Description'
WHERE objectproperty(uc.object_id,'IsUniqueCnst')= 1;

当然我们也可以调整这些语句来方便我们的精确查找,比如:

--数据库中的所有视图在过去两周内被修改的有:

SELECT name AS ViewName, convert(char(),modify_date,)

FROM sys.objects WHERE objectproperty(OBJECT_ID,'IsView')= 

AND modify_date > dateadd(week,-, GetDate());

--上个月创建的所有对象的名称和类型

SELECT coalesce(object_schema_name(obj.object_ID)+'.','')+obj.name AS ObjectName,

convert(varchar(),lower(replace(type_desc,'_',' ')))

FROM sys.objects obj

WHERE create_date > dateadd(month,-, GetDate());

--DBO架构中所有基本对象的名称和类型

SELECT coalesce(object_schema_name(obj.object_ID)+'.','')+obj.name AS ObjectName,

convert(varchar(),lower(replace(type_desc,'_',' '))) as ObjectType

FROM sys.objects obj

WHERE parent_object_ID=

AND schema_ID = schema_ID('dbo'); 

总结

  如上,到这级别简单实用足够了。们已经介绍了一般的理论,并介绍了查找数据库中的内容的基本方法。在下一篇中我将会深入介绍触发器并且找到有效信息的排序以便于可以通过系统视图从动态在线目录中收集的有用信息。

探索SQL Server元数据(一)的更多相关文章

  1. 探索SQL Server元数据(二)

    背景 上一篇中,我介绍了SQL Server 允许访问数据库的元数据,为什么有元数据,如何使用元数据.这一篇中我会介绍如何进一步找到各种有价值的信息.以触发器为例,因为它们往往一起很多问题. 那么如何 ...

  2. 探索SQL Server元数据(三):索引元数据

    背景 在第一篇中我介绍了如何访问元数据,元数据为什么在数据库里面,以及如何使用元数据.介绍了如何查出各种数据库对象的在数据库里面的名字.第二篇,我选择了触发器的主题,因为它是一个能提供很好例子的数据库 ...

  3. 人人都是 DBA(II)SQL Server 元数据

    SQL Server 中维护了一组表用于存储 SQL Server 中所有的对象.数据类型.约束条件.配置选项.可用资源等信息,这些信息称为元数据信息(Metadata),而这些表称为系统基础表(Sy ...

  4. SQL Server元数据查询

    原文:SQL Server元数据查询 1.查询触发器的信息 --查询触发器的信息 select name, --触发器名称 (select name from sys.objects where ob ...

  5. SQL Server 元数据分类

    SQL Server 中维护了一组表用于存储 SQL Server 中所有的对象.数据类型.约束条件.配置选项.可用资源等信息,这些信息称为元数据信息(Metadata),而这些表称为系统基础表(Sy ...

  6. SQL Server元数据损坏(metadata corruption)修复

    在升级一个SQL Server 2000的数据库时,遇到了一致性错误,其中有几个错误是元数据损坏(metadata corruption),特意研究了一下这个案例,因为以前也零零散散的遇到过一些一致性 ...

  7. 如何获取SQL Server数据库元数据的方法

    发布时间:2007.06.15 05:05    来源:赛迪网    作者:3946469 元数据简介 元数据 (metadata) 最常见的定义为“有关数据的结构数据”,或者再简单一点就是“关于数据 ...

  8. 使用WinDbg调试SQL Server——入门

    这篇文章我想探究下SQL Server里完全不同的领域:如果使用WinDbg(来自针对Windows的调试工具)调试SQL Server.在我们进入枯涩细节之前,我想详细解释下为什么选择这样晦涩的话题 ...

  9. 谈一谈SQL Server中的执行计划缓存(上)

    简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...

随机推荐

  1. 2.SDL规范文档

    01.安全设计Checklist 输入验证 校验跨信任边界传递的不可信数据(策略检查数据合法性,含白名单机制等)格式化字符串时,依然要检验用户输入的合法性,避免可造成系统信息泄露或者拒绝服务 禁止向J ...

  2. Android-----Intent中通过startActivity(Intent intent )显式启动新的Activity

    Intent:即意图,一般是用来启动新的Activity,按照启动方式分为两类:显式Intent 和 隐式Intent 显示Intent就是直接以“类名称”来指定要启动哪一个Activity:Inte ...

  3. 为View设置左右切换动画

    本文同步自http://javaexception.com/archives/64 问题: 近期的需求中,碰到了一个view切换动画的需求.要实现的是点击按钮,从左到右滑动view,左边的view消失 ...

  4. 安卓4.0以上系统怎么不用root激活XPOSED框架的方法

    在大多单位的引流或业务操作中,基本上都需要使用安卓的高端技术Xposed框架,近期,我们单位购买了一批新的安卓4.0以上系统,基本上都都是基于7.0以上版本,基本上都不能够刷入root超级权限,即便是 ...

  5. pc蛋蛋app开发定制

    如今的pc蛋蛋app开发和pc蛋蛋软件开发互联网已经不再是一个新兴行业,对打仗的团队也要求更加正规化.对于产品技术运营市场等角色来说,如果每个人都能有比较全面的视野,那这个产业将是一个全新的趋势,单一 ...

  6. SpringMVC 参数传递和接收的几种方式

    普通传参 测试项目:SpringBoot2.0.不使用 form 表单传参,后端不需要指定 consumes . 使用 Postman 进行测试. @PathVariable 只能接收 URL 路径里 ...

  7. 微信小程序报错,不在以下 request 合法域名列表中(引起的探索)

       最近因为突然对小程序有兴趣,然后开始了自学之旅.     在学习的过程当中遇到了一个问题,控制台报错,提示:不在以下 request 合法域名列表中,如下图所示 然后我就开始了搜索之旅,相对觉得 ...

  8. Eureka源码探索(一)-客户端服务端的启动和负载均衡

    1. Eureka源码探索(一)-客户端服务端的启动和负载均衡 1.1. 服务端 1.1.1. 找起始点 目前唯一知道的,就是启动Eureka服务需要添加注解@EnableEurekaServer,但 ...

  9. 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下)

    上一篇文章:https://www.cnblogs.com/cgzl/p/9734083.html 处理数据 嵌套字段 看例子: 我想查看viewer下的repositories.注意里面的edges ...

  10. JS ES6的变量的结构赋值

    变量的结构赋值用户很多 1.交换变量的值 let x = 1; let y = 2; [x,y] = [y,x] 上面的代码交换变量x和变量y的值,这样的写法不仅简洁,易读,语义非常清晰 2.从函数返 ...