数据库表的基本信息,你真的都了解吗?

数据库
我们要讲的正是最基础的数据库表的基本信息,这些知识你真的全部都了解了吗?还是带着疑问来看本文吧。

用SQL Doc生成数据库字典文档的时候,突然发现有字段描叙(Description)这项内容,以前一直没有注意过,故特意研究了一下,结果越挖越深,就写了这篇文章。

以前在做数据库脚本开发时,新建表时,对各个字段的描叙要么是记录在文档里面,要么自己建一个表,来保存这些内容,以便日后开发、维护的方便。其实这些信息完全可以放在数据库自己的系统视图里面。

对字段的说明、描述一般都放在系统视图sys.extended_properties中,例如(表dbo.Employee的字段Department的说明

  1. SELECT * FROM dbo.Employee  
  2. SELECT * FROM sys.extended_properties  

其中 当class =1时,major_id它的值是dbo.Employee的id,minor_id是Department的id(详细信息参见MSDN),如下图所示

  1. SELECT OBJECT_ID(N'dbo.Employee')  
  2. SELECT  column_id FROM    sys.columns  
  3. WHERE   object_id = OBJECT_ID('dbo.Employee')  
  4.         AND name = 'Department' 

其实在MSSMS 管理器中,选中要添加字段说明的表,单击右键——》修改(08是设计),如下图所示,增加后,保存。就会在sys.extended_properties里添加相应的记录。

当然你也可以用脚本命令添加数据库表的字段说明

  1. EXEC sp_addextendedproperty N'MS_Description', N'雇员名称', 'SCHEMA', N'dbo', 'TABLE', N'Employee', 'COLUMN', N'EmployeeName'  

如果已经存在刚才记录,你再执行上面这段脚本,就会提示:

消息 15233,级别 16,状态 1,过程 sp_addextendedproperty,第 38 行
无法添加属性。'dbo.Employee.EmployeeName' 已存在属性 'MS_Description'。

下面看看工具生成的文档,工具生成这些信息肯定是数据库里存有对象的这些信息,下面我们来看看这些信息都是从何而来吧


 

 这里先列举一些保存表信息的系统表、视图吧,可能有些遗漏了,实在太多了,要仔细把这些全部列举出来还得花费一番功夫

  1. SELECT * FROM sys.columns  
  2.  
  3. --为每个表和视图中的每列返回一行,并为数据库中的存储过程的每个参数返回一行。  
  4. SELECT * FROM syscolumns  
  5.  
  6. --每个表对象的信息  
  7. SELECT * FROM sys.tables  
  8.  
  9. SELECT * FROM sysobjects  
  10.  
  11. --在数据库中创建的每个用户定义的架构范围内的对象的信息  
  12. SELECT * FROM sys.objects  
  13.  
  14. --数据库实例中的每个数据库的信息  
  15. SELECT * FROM sys.databases  
  16.  
  17. --系统数据类型  
  18. SELECT * FROM sys.types  
  19.  
  20. --含数据库中每个视图、规则、默认值、触发器、CHECK 约束、DEFAULT 约束和存储过程的项  
  21. SELECT * FROM dbo.syscomments  
  22.  
  23. --保存表的自增列信息  
  24. SELECT * FROM sys.identity_columns 

下面来看看属性那栏的信息保存在那些表里面。如果表是数据库的默认排序规则,就可以用下面脚本。 

  1. SELECT  create_date  AS Created ,  
  2.         modify_date  AS Last Modified,  
  3.         ( SELECT    collation_name  
  4.           FROM      sys.databases  
  5.           WHERE     name = 'MyAssistant' 
  6.         ) AS collation_name  
  7. FROM    SYS.tables  
  8. WHERE   NAME = 'Employee' 

如果用某个列的排序规则可用下面的脚本

  1. SELECT  create_date  AS Created,  
  2.         modify_date  AS Last Modified,  
  3.         ( SELECT DISTINCT 
  4.                     collation  
  5.           FROM      syscolumns  
  6.           WHERE     id = OBJECT_ID(N'dbo.Employee')  
  7.                     AND collation IS NOT NULL 
  8.                     AND name ='EmployeeName' 
  9.         ) AS collation_name  
  10. FROM    sys.tables  
  11. WHERE   NAME = 'Employee' 

查看数据库的排序规则可以从 sys.databases查看,而表的某个列的排序规则信息保存在syscolumns里面。上图的Heap, Row Count信息我还不知是从哪里来的。

接下来看看Cloumns信息吧

  1. SELECT   
  2.     C.Name AS FieldName,  
  3.     T.Name AS DataType,  
  4.     CASE WHEN C.Max_Length = -1 THEN 'Max' ELSE CAST(C.Max_Length AS VARCHAREND AS Max_Length,  
  5.     CASE WHEN C.is_nullable = 0 THEN '×'  ELSE '√' END AS Is_Nullable,  
  6.     C.is_identity,  
  7.     ISNULL(M.text, '')  AS  DefaultValue,  
  8.     ISNULL(P.value, ''AS FieldComment  
  9.       
  10. FROM sys.columns  C  
  11. INNER JOIN  sys.types T ON C.system_type_id = T.user_type_id  
  12. LEFT JOIN dbo.syscomments M ON M.id = C.default_object_id  
  13. LEFT  JOIN sys.extended_properties P ON P.major_id = C.object_id AND C.column_id = P.minor_id   
  14. WHERE C.[object_id] = OBJECT_ID('dbo.Employee')  
  15. ORDER BY C.Column_Id ASC 

如图所示,得到结果与文档还是有些区别,我通过该脚本实现与文档一致的时候,怎么也找不到nvarchar(30)的30,这个值的出处,后来才发现它其实就是nvarchar的max_length 的一半。

修改脚本如下所示

  1. SELECT   
  2.     C.Name AS FieldName,  
  3.     CASE WHEN T.Name ='nvarchar' THEN   
  4.               T.name +'(' + CAST(C.max_length/2 AS VARCHAR) +')'   
  5.          ELSE T.name END AS DataType,  
  6.     CASE WHEN C.Max_Length = -1 THEN 'Max' ELSE CAST(C.Max_Length AS VARCHAREND AS Max_Length,  
  7.     CASE WHEN C.is_nullable = 0 THEN '×'  ELSE '√' END AS Is_Nullable,  
  8.     ISNULL(CAST(I.seed_value AS VARCHAR) + '-' + CAST(I.increment_value AS VARCHAR), ''AS is_identity,  
  9.     ISNULL(M.text, '')  AS  DefaultValue,  
  10.     ISNULL(P.value, ''AS FieldComment  
  11.       
  12. FROM sys.columns  C  
  13. INNER JOIN  sys.types T ON C.system_type_id = T.user_type_id  
  14. LEFT  JOIN  dbo.syscomments M ON M.id = C.default_object_id  
  15. LEFT  JOIN  sys.extended_properties P ON P.major_id = C.object_id AND C.column_id = P.minor_id   
  16. LEFT  JOIN  sys.identity_columns I ON I.column_id= C.column_id AND C.object_id = I.object_id  
  17. WHERE C.[object_id] = OBJECT_ID('dbo.Employee')  
  18. ORDER BY C.Column_Id ASC 

接下来看看Perssion信息来自何处。 首先我们来看看赋与、收回权限的脚本(我是在sa账号下运行的)

  1. DENY  SELECT ON [dbo].[Employee] TO [Kerry]  
  2. GO  
  3.  
  4. GO  
  5. DENY DELETE ON [dbo].[Employee] TO [Kerry]  
  6. GO  
  7.  
  8. REVOKE DELETE ON [dbo].[Employee] TO [Kerry]  
  9. GO  
  10.  
  11. REVOKE SELECT ON [dbo].[Employee] TO [Kerry]  
  12. GO  

那么这些权限信息保存在那个系统表或系统视图中,我查了很多资料,还是没有查到,呵呵,希望有知道的告诉一声。但是可以同过系统函数和系统存储过程得到一些相关的权限设置信息。

1:系统存储过程 sp_table_privileges, 它返回指定的一个或多个表的表权限(如 INSERT、DELETE、UPDATE、SELECT、REFERENCES)的列表,表具体参见(MSDN)。

2:系统函数 fn_my_permissions 返回有效授予主体对安全对象的权限的列表,表具体参见(MSDN)

EXEC sp_table_privileges @table_name = 'Employee';

EXEC sp_table_privileges @table_name ='Employee' , @table_owner ='dbo'


 

  1. SELECT *   
  2. FROM fn_my_permissions('dbo.Employee''OBJECT')   
  3. ORDER BY subentity_name, permission_name ;  

 

  1. --查看用户Kerry的有效权限  
  2. SELECT * FROM fn_my_permissions('Kerry''USER'); 

 

再来看看SQL Srcipt,好像没有那个系统表、系统视图保存创建表的脚本(如果有的话,算我孤陋寡闻了),也不能通过SP_HELPTEXT来得到(存储过程可以),在

网上搜索了下大概有SMO 方式和存储过程来实现的,SMO方式我还没来得及验证,存储过程倒是找到一个(本来打算自己尝试下的。呵呵,那这篇文章得耗上好长时间了,等写完了,自己再写个试试),下面的存储过程是我在http://edu.codepub.com/2009/0603/5408.php这里搜索到,也不知道原创作者是谁。

  1. If object_id('up_CreateTable') Is Not Null  
  2.     Drop Proc up_CreateTable  
  3. Go  
  4. /* 生成建表脚本(V2.0)  OK_008 2009-5-18 */  
  5. Create Proc up_CreateTable  
  6. (  
  7.     @objectList nvarchar(max)=null  
  8. )  
  9. --With ENCRYPTION  
  10. As  
  11. /*  参数说明:  
  12.     @objectList 对象列表,对象之间使用","隔开  
  13.       
  14.     改存储过程生成的建表脚本,包含Column,Constraint,Index  
  15. */  
  16. Set Nocount On  
  17.     Declare @sql nvarchar(max),  
  18.             @objectid int,  
  19.             @id int,  
  20.             @Rowcount int,  
  21.             @ObjectName sysname,  
  22.             @Enter nvarchar(2),  
  23.             @Tab nvarchar(2)  
  24.  
  25.     Select     @Enter=Char(13)+Char(10),  
  26.             @Tab=Char(9)      
  27.  
  28.     Declare @Tmp Table(name sysname)  
  29.       
  30.     If @objectList>''  
  31.     Begin  
  32.         Set @sql='Select N'''+Replace(@objectList,',',''' Union All Select N''')+''''  
  33.         Insert Into @Tmp (name) Exec(@sql)  
  34.  
  35.         Set @sql=null 
  36.         Select @sql=Isnull(@sql+',','')+name   
  37.             From @Tmp As a  
  38.             Where Not Exists(Select 1 From sys.objects Where type='U' And name=a.name)  
  39.  
  40.         If @sql>''  
  41.         Begin  
  42.             Set @sql='发现无效的表名: '+@sql  
  43.             Raiserror 50001 @sql  
  44.             Return(1)  
  45.         End  
  46.     End  
  47.  
  48.     If object_id('tempdb..#Objects') Is Not Null  
  49.         Drop Table #Objects  
  50.       
  51.     If object_id('tempdb..#Columns') Is Not Null  
  52.         Drop Table #Columns      
  53.       
  54.     Create Table #Objects(id int Identity(1,1) Primary Key,object_id int,name sysname)  
  55.  
  56.        
  57.     ;With t As   
  58.     (  
  59.     Select Object_id,Convert(int,0) As LevelNo,name As object_name  
  60.             From sys.objects a   
  61.             Where Type='U' And is_ms_shipped=0 And Not Exists(Select 1 From sys.foreign_keys Where referenced_object_id=a.object_id)  
  62.     Union All  
  63.     Select a.referenced_object_id As Object_id,b.LevelNo+1 As LevelNo,c.name As object_name  
  64.         From sys.foreign_keys a   
  65.             Inner Join t b On b.object_id=a.parent_object_id  
  66.             Inner Join sys.objects c On c.object_id=a.referenced_object_id And c.is_ms_shipped=0 
  67.     )  
  68.     Insert Into #Objects(object_id,name)  
  69.         Select a.object_id,object_name  
  70.             From t a  
  71.             Where    Not Exists(Select 1 From t Where object_id=a.object_id And LevelNo>a.LevelNo) And  
  72.                     Not Exists(Select 1 From sys.extended_properties Where major_id=a.object_id And minor_id=0 And class=1 And Name=N'microsoft_database_tools_support')  
  73.                     And (Exists(Select 1 From @Tmp Where name=a.object_name) Or Not Exists(Select 1 From @Tmp))  
  74.             Group By object_id,object_name,LevelNo  
  75.             Order By LevelNo Desc  
  76.  
  77.     Set @Rowcount=@@Rowcount  
  78.     If @Rowcount=0 
  79.     Begin  
  80.         Raiserror 50001 N'没有可以生产脚本的表!'  
  81.         Return(1)  
  82.     End  
  83.  
  84.     --Column  
  85.     Select    a.object_id,  
  86.             a.column_id As Seq,  
  87.             Cast(1 As tinyint) As DefinitionType,  
  88.             Quotename(a.name)+Char(32)+ c.name +  
  89.             Case   
  90.                 When a.user_type_id In (231,239) Then '('+Case a.max_length When -1 Then 'Max' Else Rtrim(a.max_length/2) End +')'  
  91.                 When a.user_type_id In (62,165,167,173,175) Then '('+Case a.max_length When -1 Then 'Max' Else Rtrim(a.max_length) End+')'  
  92.                 When a.user_type_id In (106,108) Then '('+Rtrim(a.[precision])+','+Rtrim(a.scale)+')'   
  93.                 Else ''  
  94.             End  
  95.             + Char(32)+  
  96.             Case a.is_rowguidcol When 1 Then 'Rowguidcol ' Else '' End +  
  97.             Case a.is_identity When 1 Then 'Identity('+Cast(d.seed_value As nvarchar(10))+','+Cast(d.increment_value As nvarchar(10))+') ' Else '' End+   
  98.             Case a.is_nullable When 1 Then 'Null ' Else 'Not Null ' End+  
  99.             Isnull('Constraint '+Quotename(e.name)+' Default('+e.definition+')','') As definition  
  100.  
  101.             Into #Columns  
  102.         From sys.columns As a  
  103.             Inner Join #Objects As b On b.object_id=a.object_id  
  104.             Inner Join sys.types As c On c.user_type_id=a.user_type_id  
  105.             Left Outer Join sys.identity_columns As d On d.object_id=a.object_id And d.column_id=a.column_id And a.is_identity=1 
  106.             Left Outer Join sys.Default_constraints As e On e.object_id=a.default_object_id And e.parent_column_id=a.column_id  
  107.  
  108.         Create Nonclustered Index IX_#Columns_object_id On #Columns(object_id Asc)  
  109.  
  110.         --Constraint  
  111.         Insert Into #Columns  
  112.       
  113.         Select    a.parent_object_id As object_id,  
  114.                 Row_number() Over(Partition By a.parent_object_id Order By Case a.type When 'PK' Then 1 When 'C' Then 2 Else 3 End)As Seq,  
  115.                 2 As DefinitionType,  
  116.                 'Alter Table '+Quotename(object_name(a.parent_object_id)) +' Add Constraint '+Quotename(a.name)+  
  117.                 Case a.type   
  118.                     When 'PK' Then ' Primary Key '+Case When Exists(Select 1 From sys.indexes Where object_id=a.parent_object_id And is_primary_key=1 And type=1) Then N'Clustered ' Else N'Nonclustered ' End+  
  119.                                                 '('+Stuff((Select ','+Quotename(c1.Name)+Case a1.is_descending_key When 1 Then ' Desc' Else ' Asc' End  
  120.                                                         From sys.index_columns As a1  
  121.                                                             Inner Join sys.indexes As b1 On b1.object_id=a1.object_id And b1.index_id=a1.index_id And b1.is_primary_key=1  
  122.                                                             Inner Join sys.columns As c1 On c1.object_id=a1.object_id And c1.column_id=a1.column_id  
  123.                                                         Where aa1.object_id=a.parent_object_id   
  124.                                                         For Xml Path('')  
  125.                                                     ),1,1,'')+  
  126.                                                 ')'  
  127.                     When 'F' Then ' Foreign Key ('+Stuff((Select ','+Quotename(b1.Name)  
  128.                                                         From sys.foreign_key_columns As a1  
  129.                                                             Inner Join sys.columns As b1 On b1.object_id=a1.parent_object_id And b1.column_id=a1.parent_column_id  
  130.                                                         Where aa1.constraint_object_id=a.object_id   
  131.                                                         Order By a1.constraint_column_id  
  132.                                                         For Xml Path('')  
  133.                                                     ),1,1,'')+  
  134.                                                 ') References '+(Select Quotename(object_name(referenced_object_id)) From  sys.foreign_keys Where object_id=a.object_id)+  
  135.                                                 ' ('  
  136.                                                     +Stuff((Select ','+Quotename(b1.Name)  
  137.                                                         From sys.foreign_key_columns As a1  
  138.                                                             Inner Join sys.columns As b1 On b1.object_id=a1.referenced_object_id And b1.column_id=a1.referenced_column_id  
  139.                                                         Where aa1.constraint_object_id=a.object_id   
  140.                                                         Order By a1.constraint_column_id  
  141.                                                         For Xml Path('')  
  142.                                                     ),1,1,'')+  
  143.                                                 ')'  
  144.                     When 'UQ' Then ' Unique'+(Select Case a1.type When 1 Then ' Clustered' Else ' Nonclustered' End  
  145.                                                     From sys.indexes As a1  
  146.                                                     Where aa1.object_id=a.parent_object_id   
  147.                                                                 And Exists(Select 1 From sys.key_constraints Where object_id=a.object_id And parent_object_id=a1.object_id And unique_index_id=a1.index_id)  
  148.                                                )+                          
  149.                                                 '('+Stuff((Select ','+Quotename(c1.Name)+Case a1.is_descending_key When 1 Then ' Desc' Else ' Asc' End  
  150.                                                         From sys.index_columns As a1  
  151.                                                             Inner Join sys.indexes As b1 On b1.object_id=a1.object_id And b1.index_id=a1.index_id And b1.is_unique_constraint=1  
  152.                                                             Inner Join sys.columns As c1 On c1.object_id=a1.object_id And c1.column_id=a1.column_id  
  153.                                                         Where aa1.object_id=a.parent_object_id   
  154.                                                                 And Exists(Select 1 From sys.key_constraints Where object_id=a.object_id And parent_object_id=a1.object_id And unique_index_id=a1.index_id)  
  155.                                                         For Xml Path('')  
  156.                                                     ),1,1,'')+  
  157.                                                 ')'  
  158.                     When 'C' Then ' Check' +(Select definition From sys.check_constraints Where object_id=a.object_id)  
  159.                     Else ''  
  160.                 End As definition  
  161.  
  162.             From sys.objects As a  
  163.             Where a.type In('PK','F','C','UQ')  
  164.                     And Exists(Select 1  From #Objects Where object_id=a.parent_object_id)  
  165.  
  166.         --Index  
  167.         Insert Into #Columns  
  168.         Select    a.object_id ,  
  169.                 a.index_id As Seq,  
  170.                 3 As DefinitionType,  
  171.                 'Create '+Case a.is_unique When 1 Then 'Unique ' Else '' End+  
  172.                 Case a.type When 1 Then 'Clustered ' Else 'Nonclustered ' End+  
  173.                 'Index '+Quotename(a.name)+' On '+Quotename(b.name)+  
  174.                                         ' ('+Stuff((Select ','+Quotename(b1.Name)+Case a1.is_descending_key When 1 Then ' Desc' Else ' Asc' End  
  175.                                                         From sys.index_columns As a1  
  176.                                                             Inner Join sys.columns As b1 On b1.object_id=a1.object_id And b1.column_id=a1.column_id  
  177.                                                         Where aa1.object_id=a.object_id And a.index_id=a1.index_id And a1.is_included_column=0 
  178.                                                         For Xml Path('')  
  179.                                                     ),1,1,'')+  
  180.                                         ')'+  
  181.                                         Isnull(' Include('+Stuff((Select ','+Quotename(b1.Name)  
  182.                                                         From sys.index_columns As a1  
  183.                                                             Inner Join sys.columns As b1 On b1.object_id=a1.object_id And b1.column_id=a1.column_id  
  184.                                                         Where aa1.object_id=a.object_id And a.index_id=a1.index_id And a1.is_included_column=1  
  185.                                                         For Xml Path('')  
  186.                                                     ),1,1,'')+  
  187.                                         ')','')  
  188.                     As definition  
  189.             From sys.indexes As a  
  190.                 Inner Join #Objects As b On b.object_id=a.object_id  
  191.             Where a.type>0  
  192.                     And Not Exists(Select 1 From sys.key_constraints Where parent_object_id=a.object_id And unique_index_id=a.index_id)  
  193.  
  194.           
  195.  
  196.         --Print  
  197.           
  198.  
  199.         Print 'Use '+Quotename(db_name())+@Enter+'Go'+@Enter+'/* 创建表结构 Andy '+Convert(nvarchar(10),Getdate(),120)+'*/'+@Enter  
  200.  
  201.         Set @id=1 
  202.         While @id<=@Rowcount  
  203.         Begin  
  204.             Select @objectid=object_id,@ObjectName=name From #Objects Where id=@id  
  205.  
  206.             Set @Sql=@Enter+'--('+Rtrim(@id)+'/'+Rtrim(@Rowcount)+') '+@ObjectName+@Enter+'If object_id('''+Quotename(@ObjectName)+''') Is Null'+@Enter+'Begin'+@Enter+@Tab+  
  207.                     'Create Table '+Quotename(@ObjectName)+@Enter+@Tab+'('+@Enter  
  208.             Select @Sql=@Sql+@Tab+@Tab+definition+','+@Enter  
  209.                 From #Columns   
  210.                 Where object_id=@objectid   
  211.                         And DefinitionType=1 
  212.                 Group By Seq,definition  
  213.                 Order By Seq  
  214.             Set @sql=Substring(@sql,1,Len(@sql)-3)+@Enter+@Tab+')'+@Enter  
  215.             Select @Sql=@Sql+@Tab+definition+@Enter  
  216.                 From #Columns   
  217.                 Where object_id=@objectid   
  218.                         And DefinitionType>1  
  219.                 Group By DefinitionType,Seq,definition  
  220.                 Order By Seq  
  221.  
  222.             Print Substring(@sql,1,Len(@sql)-2)+@Enter+'End'  
  223.             Set @id=@id+1  
  224.         End  
  225.  
  226.         Print 'Go'  
  227.  
  228.     Drop Table #Columns  
  229.     Drop Table #Objects  
  230. Go 

原文标题:数据库表的基本信息,你知道吗?

链接:http://www.cnblogs.com/kerrycode/archive/2010/09/03/1816611.html

责任编辑:彭凡 来源: 博客园
相关推荐

2017-10-18 22:01:12

2022-07-26 00:00:22

HTAP系统数据库

2014-04-17 16:42:03

DevOps

2018-12-27 10:46:20

数据库工程师DBA

2021-01-15 07:44:21

SQL注入攻击黑客

2021-11-09 09:48:13

Logging python模块

2019-09-16 08:40:42

2023-03-16 10:49:55

2020-02-27 10:49:26

HTTPS网络协议TCP

2014-11-28 10:31:07

Hybrid APP

2021-03-28 09:26:30

HttpHttp协议网络协议

2009-12-03 15:40:41

PHP获取数据库表信息

2021-11-26 08:07:16

MySQL SQL 语句数据库

2023-11-01 13:48:00

反射java

2018-01-06 10:38:51

Ping抓包 ICMP协议

2012-05-31 09:56:54

云安全

2022-03-14 07:53:27

ELTETL大数据

2023-10-24 08:53:24

FutureTas并发编程

2015-07-31 10:35:18

实时计算

2019-11-06 09:52:01

JavaScript单线程非阻塞
点赞
收藏

51CTO技术栈公众号