SQL经典实例——元数据查询

元数据查询

1、列出模式中的所有表

问题:你想列出自己在给定模式中创建的所有表。

解决方案:下面的所有解决方案都假设你使用的模式为 SMEAGOL。在所有 RDBMS 中,解决方案采用的基本方法都相同------查询系统表(视图)​。对于数据库中的每张表,这个系统表(视图)都包含一行与之相关的信息。

DB2:查询 SYSCAT.TABLES。

sql 复制代码
select tabname
from syscat.tables
where tabschema = 'SMEAGOL';

Oracle:查询 SYS.ALL_TABLES。

sql 复制代码
select table_name
from all_tables
where owner = 'SMEAGOL';

查询 INFORMATION_SCHEMA.TABLES。

sql 复制代码
select table_name
from information_schema.tables
where table_schema = 'SMEAGOL'

暴露有关自己的信息时,数据库使用的正是你为自己的应用程序创建的机制------表和视图,这有点儿循环的"味道"​。例如,Oracle 维护着一个庞大的系统视图(如ALL_TABLES)目录,你可以通过查询这些视图来获取有关表、索引、授权(grant)和其他数据库对象的信息。

Oracle 的目录视图仅仅是视图。它们基于一组底层表,这些底层表包含的信息不便于用户读取。这些视图让用户能够轻松地使用Oracle 的目录数据。

Oracle 系统视图和 DB2 系统表都是厂商专用的,而PostgreSQL、MySQL 和 SQL Server 支持信息模式------ISO SQL 标准定义的一组视图,因此有些查询适用于这 3种 RDBMS。

2、列出表中的列

问题:你想列出表中的列,以及这些列的数据类型和在表中的位置。

解决方案:下面的解决方案假设你要列出模式 SMEAGOL 中 EMP 表的列及其数据类型和用数字表示的位置。

DB2:查询 SYSCAT.COLUMNS。

sql 复制代码
select colname, typename, colno
from syscat.columns
where tabname   = 'EMP'
and tabschema = 'SMEAGOL'

Oracle:查询 ALL_TAB_COLUMNS。

sql 复制代码
select column_name, data_type, column_id
from all_tab_columns
where owner      = 'SMEAGOL'
and table_name = 'EMP'

PostgreSQL、MySQL 和 SQL Server:查询 INFORMATION_SCHEMA.COLUMNS。

sql 复制代码
select column_name, data_type, ordinal_position
from information_schema.columns
where table_schema = 'test'
and table_name = 'emp';

3、列出表的索引列

问题:你想列出给定表的索引、索引基于的列以及这些列在索引中的位置(如果有的话)​。

解决方案:下面的解决方案随 RDBMS 而异,但假设你要列出模式SMEAGOL 中 EMP 表的索引。

DB2:查询 SYSCAT.INDEXES。

sql 复制代码
select a.tabname, b.indname, b.colname, b.colseq
from syscat.indexes a,syscat.indexcoluse b
where a.tabname   = 'EMP'
and a.tabschema = 'SMEAGOL'
and a.indschema = b.indschema
and a.indname   = b.indname

Oracle:查询 SYS.ALL_IND_COLUMNS。

sql 复制代码
select table_name, index_name, column_name, column_position
from sys.all_ind_columns
where table_name  = 'EMP'
and table_owner = 'SMEAGOL'

PostgreSQL:查询 PG_CATALOG.PG_INDEXES 和INFORMATION_SCHEMA.COLUMNS。

sql 复制代码
select a.tablename,a.indexname,b.column_name
from pg_catalog.pg_indexes a,information_schema.columns b
where a.schemaname = 'SMEAGOL'
and a.tablename  = b.table_name

MySQL:使用命令 SHOW INDEX。

sql 复制代码
show index from emp;

SQL Server:查询 SYS.TABLES、SYS.INDEXES、SYS.INDEX_COLUMNS 和 SYS.COLUMNS。

sql 复制代码
select a.name table_name,
       b.name index_name,
       d.name column_name,
       c.index_column_id
from sys.tables a,
       sys.indexes b,
       sys.index_columns c,
       sys.columns d
where a.object_id = b.object_id
and b.object_id = c.object_id
and b.index_id  = c.index_id
and c.object_id = d.object_id
and c.column_id = d.column_id
and a.name = 'EMP'

4、列出表的约束

问题:你想列出给表定义的约束以及这些约束是在哪些列上定义的。例如,你想获悉 EMP 表的约束以及这些约束是在哪些列上定义的。

解决方案

DB2:查询 SYSCAT.TABCONST 和 SYSCAT.COLUMNS。

sql 复制代码
select a.tabname, a.constname, b.colname, a.type
from syscat.tabconst a,syscat.columns b
where a.tabname   = 'EMP'
and a.tabschema = 'SMEAGOL'
and a.tabname   = b.tabname
and a.tabschema = b.tabschema

Oracle:查询 SYS.ALL_CONSTRAINTS 和SYS.ALL_CONS_COLUMNS。

sql 复制代码
select a.table_name,
      a.constraint_name,
       b.column_name,
       a.constraint_type
from all_constraints a,all_cons_columns b
where a.table_name      = 'EMP'
and a.owner           = 'SMEAGOL'
and a.table_name      = b.table_name
and a.owner           = b.owner
and a.constraint_name = b.constraint_name

PostgreSQL、MySQL 和 SQL Server:查询 INFORMATION_SCHEMA.TABLE_CONSTRAINTS和 INFORMATION_SCHEMA.KEY_COLUMN_USAGE。

sql 复制代码
select a.table_name,
			 a.constraint_name,
			 b.column_name,
			 a.constraint_type
from information_schema.table_constraints a, information_schema.key_column_usage b
where a.table_name = 'emp'
	and a.table_schema = 'test'
	and a.table_name = b.table_name
	and a.table_schema = b.table_schema
	and a.constraint_name = b.constraint_name;

5、列出没有相应索引的外键

问题:你想列出没有相应索引的外键,例如,你想知道是否在EMP 表的外键上创建了索引。

解决方案

`DB2查询 SYSCAT.TABCONST、SYSCAT.KEYCOLUSE、SYSCAT.INDEXES 和 SYSCAT.INDEXCOLUSE。

sql 复制代码
 select fkeys.tabname,
        fkeys.constname,
        fkeys.colname,
        ind_cols.indname
   from (
 select a.tabschema, a.tabname, a.constname, b.colname
   from syscat.tabconst a,
        syscat.keycoluse b
 where a.tabname    = 'EMP'
   and a.tabschema  = 'SMEAGOL'
   and a.type       = 'F'
   and a.tabname    = b.tabname
   and a.tabschema  = b.tabschema
       ) fkeys
       left join
       (
 select a.tabschema,
        a.tabname,
        a.indname,
        b.colname
   from syscat.indexes a,
        syscat.indexcoluse b
 where a.indschema  = b.indschema
   and a.indname    = b.indname
       ) ind_cols
    on (fkeys.tabschema = ind_cols.tabschema
         and fkeys.tabname   = ind_cols.tabname
         and fkeys.colname   = ind_cols.colname )
 where ind_cols.indname is null

Oracle:查询 SYS.ALL_CONS_COLUMNS、SYS.ALL_CONSTRAINTS 和SYS.ALL_IND_COLUMNS。

sql 复制代码
 select a.table_name,
        a.constraint_name,
        a.column_name,
        c.index_name
   from all_cons_columns a,
        all_constraints b,
        all_ind_columns c
 where a.table_name      = 'EMP'
   and a.owner           = 'SMEAGOL'
   and b.constraint_type = 'R'
   and a.owner           = b.owner
   and a.table_name      = b.table_name
   and a.constraint_name = b.constraint_name
   and a.owner           = c.table_owner (+)
   and a.table_name      = c.table_name (+)
   and a.column_name     = c.column_name (+)
   and c.index_name      is null

查询 INFORMATION_SCHEMA.KEY_COLUMN_USAGE、INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS、INFORMATION_SCHEMA.COLUMNS 和PG_CATALOG.PG_INDEXES。

sql 复制代码
 select fkeys.table_name,
        fkeys.constraint_name,
        fkeys.column_name,
        ind_cols.indexname
   from (
 select a.constraint_schema,
        a.table_name,
        a.constraint_name,
        a.column_name
   from information_schema.key_column_usage a,
        information_schema.referential_constraints b
  where a.constraint_name   = b.constraint_name
    and a.constraint_schema = b.constraint_schema
    and a.constraint_schema = 'SMEAGOL'
    and a.table_name        = 'EMP'
        ) fkeys
        left join
        (
 select a.schemaname, a.tablename, a.indexname, b.column_name
   from pg_catalog.pg_indexes a,
        information_schema.columns b
  where a.tablename  = b.table_name
    and a.schemaname = b.table_schema
        ) ind_cols
     on ( fkeys.constraint_schema = ind_cols.schemaname
         and fkeys.table_name     = ind_cols.tablename
         and fkeys.column_name    = ind_cols.column_name )
 where ind_cols.indexname is null select fkeys.table_name,
        fkeys.constraint_name,
        fkeys.column_name,
        ind_cols.indexname
   from (
 select a.constraint_schema,
        a.table_name,
        a.constraint_name,
        a.column_name
   from information_schema.key_column_usage a,
        information_schema.referential_constraints b
  where a.constraint_name   = b.constraint_name
    and a.constraint_schema = b.constraint_schema
    and a.constraint_schema = 'SMEAGOL'
    and a.table_name        = 'EMP'
        ) fkeys
        left join
        (
 select a.schemaname, a.tablename, a.indexname, b.column_name
   from pg_catalog.pg_indexes a,
        information_schema.columns b
  where a.tablename  = b.table_name
    and a.schemaname = b.table_schema
        ) ind_cols
     on ( fkeys.constraint_schema = ind_cols.schemaname
         and fkeys.table_name     = ind_cols.tablename
         and fkeys.column_name    = ind_cols.column_name )
 where ind_cols.indexname is null

MySQL:可以使用命令 SHOW INDEX 来检索索引信息,比如索引的名称、索引包含的列,以及这些列在索引中的序数位置。另外,可以通过查询INFORMATION_SCHEMA.KEY_COLUMN_USAGE 来列出给定表的外键。在 MySQL 5 中,据说会自动在外键上创建索引,但实际上可能被删除。要确定外键列对应的索引是否被删除了,可以执行命令 SHOW INDEX,并将其输出同查询INFORMATION_SCHEMA.KEY_COLUMN_USAGE.COLUMN_NAME 的结果进行比较。如果 COLUMN_NAME 包含在KEY_COLUMN_USAGE 中,但命令 SHOW INDEX 没有返回它,那么便可确定没有在该列上创建索引。

SQL Server:查询 SYS.TABLES、SYS.FOREIGN_KEYS、SYS.COLUMNS、SYS.INDEXES 和SYS.INDEX_COLUMNS。

sql 复制代码
 select fkeys.table_name,
        fkeys.constraint_name,
        fkeys.column_name,
        ind_cols.index_name
   from (
 select a.object_id,
        d.column_id,
        a.name table_name,
        b.name constraint_name,
        d.name column_name
   from sys.tables a
        join
        sys.foreign_keys b
     on ( a.name          = 'EMP'
          and a.object_id = b.parent_object_id
        )
        join
        sys.foreign_key_columns c
    on (  b.object_id = c.constraint_object_id )
       join
       sys.columns d
    on (    c.constraint_column_id = d.column_id
        and a.object_id            = d.object_id
       )
       ) fkeys
       left join
       (
select a.name index_name,
       b.object_id,
       b.column_id
  from sys.indexes a,
       sys.index_columns b
 where a.index_id = b.index_id
       ) ind_cols
    on (     fkeys.object_id = ind_cols.object_id
         and fkeys.column_id = ind_cols.column_id )
where ind_cols.index_name is null

6、使用SQL生成SQL

问题:你想创建动态 SQL 语句,目的可能是要自动执行维护任务。具体地说,你要完成 3 项任务:计算表中的行数,禁用给表定义的外键约束,根据表中的数据生成插入脚本。

解决方案:使用字符串来创建 SQL 语句,对于其中需要填入的值(比如命令针对的对象的名称)将由来自表的数据提供。别忘了,这里的查询只生成语句,你必须通过脚本(或其他执行 SQL 语句的方式)手动执行它们。下面的解决方案适用于 Oracle 系统,对于其他 RDBMS,采用的方法完全相同,唯一不同的是数据字典的名称和日期格式等。下面显示的输出是在我的笔记本计算机的 Oracle 实例中执行这些查询时得到的,你执行这些查询时,返回的结果集肯定不一样。

sql 复制代码
/* 生成计算所有表中行数的SQL */

select 'select count(*) from '||table_name||';' cnts
  from user_tables;

CNTS
----------------------------------------
select count(*) from ANT;
select count(*) from BONUS;
select count(*) from DEMO1;
select count(*) from DEMO2;
select count(*) from DEPT;
select count(*) from DUMMY;
select count(*) from EMP;
select count(*) from EMP_SALES;
select count(*) from EMP_SCORE;
select count(*) from PROFESSOR;
select count(*) from T;
select count(*) from T1;
select count(*) from T2;
select count(*) from T3;
select count(*) from TEACH;
select count(*) from TEST;
select count(*) from TRX_LOG;
select count(*) from X;

/* 禁用所有表中定义的外键约束 */

select 'alter table '||table_name||
       ' disable constraint '||constraint_name||';' cons
  from user_constraints
 where constraint_type = 'R';

CONS
------------------------------------------------
alter table ANT disable constraint ANT_FK;
alter table BONUS disable constraint BONUS_FK;
alter table DEMO1 disable constraint DEMO1_FK;
alter table DEMO2 disable constraint DEMO2_FK;
alter table DEPT disable constraint DEPT_FK;
alter table DUMMY disable constraint DUMMY_FK;
alter table EMP disable constraint EMP_FK;
alter table EMP_SALES disable constraint EMP_SALES_FK;
alter table EMP_SCORE disable constraint EMP_SCORE_FK;
alter table PROFESSOR disable constraint PROFESSOR_FK;

/* 根据EMP表的一些列生成插入脚本 */

select 'insert into emp(empno,ename,hiredate) '||chr(10)||
       'values( '||empno||','||''''||ename
       ||''',to_date('||''''||hiredate||''') );' inserts
  from emp
 where deptno = 10;

INSERTS
--------------------------------------------------
insert into emp(empno,ename,hiredate)
values( 7782,'CLARK',to_date('09-JUN-2006 00:00:00') );

insert into emp(empno,ename,hiredate)
values( 7839,'KING',to_date('17-NOV-2006 00:00:00') );

insert into emp(empno,ename,hiredate)
values( 7934,'MILLER',to_date('23-JAN-2007 00:00:00') );

7、描述Oracle数据库中的数据字典视图

问题:你使用的是 Oracle,但不记得有哪些数据字典视图可供你使用,更不记得这些视图的列定义。雪上加霜的是,你还无法访问 Oracle 文档。

解决方案这是一个专门针对 Oracle 的实例。Oracle 不仅维护着一组健壮的数据字典视图,还提供了包含数据字典视图文档的数据字典视图。这真是完美的循环引用。

查询视图 DICTIONARY,列出各个数据字典视图及其用途。

sql 复制代码
select table_name, comments
  from dictionary
  order by table_name;

TABLE_NAME                     COMMENTS
------------------------------ --------------------------------------------
ALL_ALL_TABLES                 Description of all object and relational
                               tables accessible to the user

ALL_APPLY                      Details about each apply process that
                               dequeues from the queue visible to the
                               current user
...

查询视图 DICT_COLUMNS,获取有关给定数据字典视图包含的列的描述。

sql 复制代码
select column_name, comments
     from dict_columns
 where table_name = 'ALL_TAB_COLUMNS';

COLUMN_NAME                     COMMENTS
------------------------------- --------------------------------------------
OWNER
TABLE_NAME                      Table, view or cluster name
COLUMN_NAME                     Column name
DATA_TYPE                       Datatype of the column
DATA_TYPE_MOD                   Datatype modifier of the column
DATA_TYPE_OWNER                 Owner of the datatype of the column
DATA_LENGTH                     Length of the column in bytes
DATA_PRECISION                  Length: decimal digits (NUMBER) or binary
                                digits (FLOAT)
相关推荐
睡不醒男孩0308232 小时前
生产环境故障销账:PostgreSQL 突发连接数暴涨与死锁,如何利用 CLup 秒级定位与解锁?
运维·数据库
2601_962054952 小时前
终端与IDE形态的vibe coding实测:两款AI编程工具迭代能力对比
数据库·ide·ai编程
万岳科技2 小时前
教育培训系统开发流程详解:平台建设关键环节解析
数据库·后端·学习
Nturmoils2 小时前
线上修一批脏数据,先别急着全量重来
数据库·后端
吴声子夜歌2 小时前
SQL经典实例——处理字符串
数据库·sql
睡不醒男孩0308232 小时前
PostgreSQL 数据库运维转型:从传统模式到 CLup 平台的 25 个核心 FAQ
运维·数据库·postgresql
凡人叶枫3 小时前
Effective C++ 条款40:明智而审慎地使用多重继承
java·数据库·c++·嵌入式开发·effective c++
至此流年莫相忘3 小时前
Spring 依赖注入三剑客:@Autowired、@Resource 与 @RequiredArgsConstructor 深度对比与实战指南
java·数据库·spring
Rain5093 小时前
2.2 数据基础:数据库集成与 ORM(TypeORM / Prisma)
数据库·人工智能·ai·数据分析·node.js·自动化·ai编程