探讨SQL利用INFORMATION_SCHEMA系统视图如何获取表的主外键信息

接着上篇文章《解析SQL 表结构信息查询 含主外键、自增长》里面提到了INFORMATION_SCHEMA视图,其实到了SQL 2005微软都主推大家使用INFORMATION_SCHEMA系统视图,而不是在使用sys东东了,当然目前还是有许多信息只能通过sys视图来查询。这里我们还是以查询表结果信息为例来说明一些主要的INFORMATION_SCHEMA视图的使用。
首先我们需要查询列的信息,这需要用到[INFORMATION_SCHEMA].[COLUMNS]系统视图来查询数据列的信息,SQL 如下:


代码如下:

SELECT  c.TABLE_SCHEMA ,
        c.TABLE_NAME ,
        c.COLUMN_NAME ,
        c.DATA_TYPE ,
        c.CHARACTER_MAXIMUM_LENGTH ,
        c.COLUMN_DEFAULT ,
        c.IS_NULLABLE ,
        c.NUMERIC_PRECISION ,
        c.NUMERIC_SCALE
FROM    [INFORMATION_SCHEMA].[COLUMNS] c
WHERE   TABLE_NAME = 'Address'

运行结果如下:

我们都知道我们在定义列的时候一般的使用都是varchar(50)之类的信息,这里我们需要整合DATA_TYPE和CHARACTER_MAXIMUM_LENGTH信息,当CHARACTER_MAXIMUM_LENGTH为-1时即使说没有指定具体最大长度,数据的指定长度信息是max,而numeric需要整合NUMERIC_PRECISION、NUMERIC_SCALE信息。修改后的SQL如下:


代码如下:

SELECT  c.TABLE_SCHEMA ,
        c.TABLE_NAME ,
        c.COLUMN_NAME ,
        CASE WHEN ( ( CHARINDEX('char', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH <> -1
                  )
             THEN c.DATA_TYPE + '('
                  + CAST(c.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(4)) + ')'
             WHEN ( ( CHARINDEX('CHAR', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH = -1
                  ) THEN c.DATA_TYPE + '(max)'
             WHEN ( CHARINDEX('numeric', c.DATA_TYPE) > 0 )
             THEN c.DATA_TYPE + '(' + CAST(c.NUMERIC_PRECISION AS VARCHAR(4))
                  + ',' + CAST(c.NUMERIC_SCALE AS VARCHAR(4)) + ')'
             ELSE c.DATA_TYPE
        END AS DATA_TYPE ,
        c.COLUMN_DEFAULT ,
        c.IS_NULLABLE ,
        c.COLUMN_DEFAULT
FROM    [INFORMATION_SCHEMA].[COLUMNS] c
WHERE   TABLE_NAME = 'Address'
ORDER BY c.ORDINAL_POSITION

运行结果如图:

现在我们需要标记这张表的那些列是主键,那些列是外键,要查询表的主、外键信息需要用到[INFORMATION_SCHEMA].[TABLE_CONSTRAINTS]和[INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] 系统视图
运行结果如图:

修改我们先前的SQL语句:


代码如下:

SELECT  c.TABLE_SCHEMA ,
        c.TABLE_NAME ,
        c.COLUMN_NAME ,
        CASE WHEN ( ( CHARINDEX('char', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH <> -1
                  )
             THEN c.DATA_TYPE + '('
                  + CAST(c.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(4)) + ')'
             WHEN ( ( CHARINDEX('CHAR', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH = -1
                  ) THEN c.DATA_TYPE + '(max)'
             WHEN ( CHARINDEX('numeric', c.DATA_TYPE) > 0 )
             THEN c.DATA_TYPE + '(' + CAST(c.NUMERIC_PRECISION AS VARCHAR(4))
                  + ',' + CAST(c.NUMERIC_SCALE AS VARCHAR(4)) + ')'
             ELSE c.DATA_TYPE
        END AS DATA_TYPE ,
        c.COLUMN_DEFAULT ,
        c.IS_NULLABLE ,
        c.COLUMN_DEFAULT ,
        CASE WHEN tc.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 'YES'
             ELSE 'NO'
        END AS IS_PRIMARY_KEY ,
        CASE WHEN tc.CONSTRAINT_TYPE = 'FOREIGN KEY' THEN 'YES'
             ELSE 'NO'
        END AS IS_FOREIGN_KEY
FROM    [INFORMATION_SCHEMA].[COLUMNS] c
        LEFT JOIN [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
                                                              AND kcu.TABLE_NAME = c.TABLE_NAME
                                                              AND kcu.COLUMN_NAME = c.COLUMN_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[TABLE_CONSTRAINTS] tc ON tc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA
                                                              AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
WHERE   c.TABLE_NAME = 'Address'
ORDER BY c.ORDINAL_POSITION

运行结果如图:

现在我们已经知道那些列是主键那些是外键,接下来的就是外键列所关联的外检表信息,这里需要用到[INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS]系统视图,运行该视图如下:

所以修改我们的SQL如下:


代码如下:

SELECT  c.TABLE_SCHEMA ,
        c.TABLE_NAME ,
        c.COLUMN_NAME ,
        CASE WHEN ( ( CHARINDEX('char', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH <> -1
                  )
             THEN c.DATA_TYPE + '('
                  + CAST(c.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(4)) + ')'
             WHEN ( ( CHARINDEX('CHAR', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH = -1
                  ) THEN c.DATA_TYPE + '(max)'
             WHEN ( CHARINDEX('numeric', c.DATA_TYPE) > 0 )
             THEN c.DATA_TYPE + '(' + CAST(c.NUMERIC_PRECISION AS VARCHAR(4))
                  + ',' + CAST(c.NUMERIC_SCALE AS VARCHAR(4)) + ')'
             ELSE c.DATA_TYPE
        END AS DATA_TYPE ,
        c.COLUMN_DEFAULT ,
        c.IS_NULLABLE ,
        c.COLUMN_DEFAULT ,
        CASE WHEN tc.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 'YES'
             ELSE 'NO'
        END AS IS_PRIMARY_KEY ,
        CASE WHEN tc.CONSTRAINT_TYPE = 'FOREIGN KEY' THEN 'YES'
             ELSE 'NO'
        END AS IS_FOREIGN_KEY,
        fkcu.COLUMN_NAME AS FOREIGN_KEY,
        fkcu.TABLE_NAME AS FOREIGN_TABLE
FROM    [INFORMATION_SCHEMA].[COLUMNS] c
        LEFT JOIN [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
                                                              AND kcu.TABLE_NAME = c.TABLE_NAME
                                                              AND kcu.COLUMN_NAME = c.COLUMN_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[TABLE_CONSTRAINTS] tc ON tc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA
                                                              AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS] fc ON kcu.CONSTRAINT_SCHEMA = fc.CONSTRAINT_SCHEMA
                                                              AND kcu.CONSTRAINT_NAME = fc.CONSTRAINT_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] fkcu ON fkcu.CONSTRAINT_SCHEMA = fc.UNIQUE_CONSTRAINT_SCHEMA
                                                              AND fkcu.CONSTRAINT_NAME = fc.UNIQUE_CONSTRAINT_NAME
WHERE   c.TABLE_NAME = 'Address'
ORDER BY c.ORDINAL_POSITION

运行结果如图:

我们的查询结果中显示了太多的NULL,看着不怎么舒服,还有我们的表名应该显示一次就可以,修改SQL如下:


代码如下:

SELECT  CASE WHEN c.ORDINAL_POSITION = 1
             THEN c.TABLE_SCHEMA + '.' + c.TABLE_NAME
             ELSE ''
        END AS TABLE_NAME ,
        c.COLUMN_NAME ,
        CASE WHEN ( ( CHARINDEX('char', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH <> -1
                  )
             THEN c.DATA_TYPE + '('
                  + CAST(c.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(4)) + ')'
             WHEN ( ( CHARINDEX('CHAR', c.DATA_TYPE) > 0
                      OR CHARINDEX('binary', c.DATA_TYPE) > 0
                    )
                    AND c.CHARACTER_MAXIMUM_LENGTH = -1
                  ) THEN c.DATA_TYPE + '(max)'
             WHEN ( CHARINDEX('numeric', c.DATA_TYPE) > 0 )
             THEN c.DATA_TYPE + '(' + CAST(c.NUMERIC_PRECISION AS VARCHAR(4))
                  + ',' + CAST(c.NUMERIC_SCALE AS VARCHAR(4)) + ')'
             ELSE c.DATA_TYPE
        END AS DATA_TYPE ,
        ISNULL(c.COLUMN_DEFAULT, '') AS COLUMN_DEFAULT ,
        CASE WHEN c.IS_NULLABLE = 'YES' THEN '√'
             ELSE ''
        END IS_NULLABLE ,
        CASE WHEN tc.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN '√'
             ELSE ''
        END AS IS_PRIMARY_KEY ,
        CASE WHEN tc.CONSTRAINT_TYPE = 'FOREIGN KEY' THEN '√'
             ELSE ''
        END AS IS_FOREIGN_KEY ,
        ISNULL(fkcu.COLUMN_NAME, '') AS FOREIGN_KEY ,
        ISNULL(fkcu.TABLE_NAME, '') AS FOREIGN_TABLE
FROM    [INFORMATION_SCHEMA].[COLUMNS] c
        LEFT JOIN [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] kcu ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
                                                              AND kcu.TABLE_NAME = c.TABLE_NAME
                                                              AND kcu.COLUMN_NAME = c.COLUMN_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[TABLE_CONSTRAINTS] tc ON tc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA
                                                              AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS] fc ON kcu.CONSTRAINT_SCHEMA = fc.CONSTRAINT_SCHEMA
                                                              AND kcu.CONSTRAINT_NAME = fc.CONSTRAINT_NAME
        LEFT JOIN [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] fkcu ON fkcu.CONSTRAINT_SCHEMA = fc.UNIQUE_CONSTRAINT_SCHEMA
                                                              AND fkcu.CONSTRAINT_NAME = fc.UNIQUE_CONSTRAINT_NAME
WHERE   c.TABLE_NAME = 'Address'
ORDER BY c.ORDINAL_POSITION

运行结果如图:

有不对的地方还请大家拍砖!

(0)

相关推荐

  • 探讨SQL利用INFORMATION_SCHEMA系统视图如何获取表的主外键信息

    接着上篇文章<解析SQL 表结构信息查询 含主外键.自增长>里面提到了INFORMATION_SCHEMA视图,其实到了SQL 2005微软都主推大家使用INFORMATION_SCHEMA系统视图,而不是在使用sys东东了,当然目前还是有许多信息只能通过sys视图来查询.这里我们还是以查询表结果信息为例来说明一些主要的INFORMATION_SCHEMA视图的使用.首先我们需要查询列的信息,这需要用到[INFORMATION_SCHEMA].[COLUMNS]系统视图来查询数据列的信息,SQ

  • 解析SQL 表结构信息查询 含主外键、自增长

    最近项目需要做什么数据字典,需要表结构信息.在网上看了许多关于表结构信息的查询,感觉都不怎么样.相对好一点就是<基于SQL2005 SQL2008 表结构信息查询升级版的详解(含外键信息)> ,但是这里有一点小问题,缺少一个过滤以致运行有一点小bug.在AdventureWorks2012数据库中的Address表查询结果如图:在查询过滤中我们添加以下信息就ok了:AND g.class_desc = 'OBJECT_OR_COLUMN'修改后的SQL如下: 复制代码 代码如下: SELECT

  • 如何获取SqlServer2005表结构(字段,主键,外键,递增,描述)

    1.获取表的基本字段属性 复制代码 代码如下: --获取SqlServer中表结构 SELECT syscolumns.name,systypes.name,syscolumns.isnullable,syscolumns.length FROM syscolumns, systypes WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id('你的表名') 运行效果 2.如果还想要获取字段的描述

  • Oracle系统表外键的更名

    正在看的ORACLE教程是:Oracle系统表外键的更名. Oracle中表的外键是保证系统参照完整性的手段,而参照完整性是指分布在两个表中的列所满足的具有主从性质的约束关系.外键涉及到两个表,其中一个称之为父项表,另一个称之为子项表. 父项表(parent table)是参照约束的基础,即通过检查这张表的有效数据情况来判断约束是否成立,它是参照约束的条件,影响约束,而不受约束的任何影响. 子项表(child table)是参照约束的对象,当其发生变化,如有新数据输入时,通过比较父项表中的有效数

  • SQL Server主键与外键设置以及相关理解

    目录 一.定义与作用 二.SSMS设置表的主键与外键 1.利用SQL语句建立查询设置 2.利用鼠标点击操作创建(SSMS环境下) 三.主键表与外键表(个人的总结与反思...) 补充:SQL Server的主键与外键约束 总结 一.定义与作用 主键:表中能够唯一地辨别事物的属性.通过主键能够查询出表中一条完整的记录,同时使用主键能防止表中出现重复的记录,避免了数据的冗余. 外键:通俗讲就是表中一个属性是来自另一张表的主键,该属性被称为该表的外键,外键可以有不止一个.外键存在的意义就是将事物与事物之

  • Django REST Framework序列化外键获取外键的值方法

    需求:序列化外键,获取外键的除id之外的值 使用Django REST Framework虽然开发接口快速,但是如果想要获取到除外键id值之外的外键信息,直接继承serializers.ModelSerializer类,然后在fields中指定返回的字段是获取不到外键的其他值的,比如我现在需要外键的name属性值,下面就给大家介绍两种方法通过序列化外键来获取我们想要的外键的值. 这里有两个Model:问卷(Questionnaire):问题(Question).一张问卷中包含多个问题,问题通过外

  • Sql Server中的系统视图详细介绍

    本来想这个系列写点什么好呢,后来想想大家作为程序员,用的最多的莫过于数据库了,但是事实上很多像我这样工作在一线的码农,对sql都一知半解,别谈优化和对数据库底层的认识了,我也是这样...  一:那些系统视图 1. 系统视图是干什么呢? 从名字上看就知道,系统视图嘛?猜的不错的话,就是存放一些sqlserver系统的一些信息,很好,恭喜你,答对了.  2. 都定义在哪呢?  为了让你眼见为实,下面截图看看,从截图中你可以看到,不管是"系统数据库"还是"用户数据库"都是

  • C#利用win32 Api 修改本地系统时间、获取硬盘序列号

    C#利用win32 Api 修改本地系统时间.获取硬盘序列号,可以用于软件注册机制的编写! 复制代码 代码如下: using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace Fengyun {     public class Win32     {         #region 修改本地系统时间         [DllIm

  • 细说SQL Server中的视图

    1,什么是视图? 2,为什么要用视图: 3,视图中的ORDER BY; 4,刷新视图: 5,更新视图: 6,视图选项: 7,索引视图: 1.什么是视图 视图是由一个查询所定义的虚拟表,它与物理表不同的是,视图中的数据没有物理表现形式,除非你为其创建一个索引:如果查询一个没有索引的视图,Sql Server实际访问的是基础表. 如果你要创建一个视图,为其指定一个名称和查询即可.Sql Server只保存视图的元数据,用户描述这个对象,以及它所包含的列,安全,依赖等.当你查询视图时,无论是获取数据还

  • SQL语句去掉重复记录,获取重复记录

    SQL语句去掉重复记录,获取重复记录  --查询一个表中有效去掉重复的记录,UserID为自增长主键,RoleID为重复字段 SELECT MIN(UserID) AS UserID, RoleID FROM tmpTable GROUP BY RoleID SELECT RoleID FROM tmpTable GROUP BY RoleID HAVING (COUNT(*) > 1) SELECT DISTINCT * FROM tmpTable sql语句查询 sql server acc

随机推荐