前言:
这节课,我们来了解一下数据库表中的约束概念,以及如何进行复合查询,最后对数据库表内的索引及分区来做一个了解。
数据库表中的约束
数据完整性
数据库不仅仅是存储数据,它也必须保证所保存的数据的正确性。如果数据不正确或不一致,那么该数据的完整性可能会遭到破坏,从而给数据库本身的可靠性带来意想不到的问题。
为了维护数据库中的数据完整性,在创建表时通常需要指定一些约束。通过表中的字段(列)定义约束,就可以防止非法数据的插入问题.对约束的定义可以在create table
语句中进行,也可以在alter table
语句中进行。
什么是约束
约束是表级的强制规定,根据约束的作用域,约束又可分为表级约束和列级约束两种。
列级约束是指是字段定义的一部分,只能够应用在一个列上。
表级约束是指独立于列的定义,可以应用于一个表中的多个列上。
在oracle系统中定义约束时,通过constraint
关键字为约束命名,如果用户没有为约束指定名称,系统会自动建立默认的名称。
常见约束学习
主键约束
应用场景:
当数据库中的某几条记录信息完全一致时,则SQL语句无法对其中指定的一条记录进行操作,这时我们需要为数据表增加一个主键字段,以确保记录与记录之间的差异性。
语法:primary keycreate table table_name ( column_name1 column_type1 primary key[, column_name2 column_type2[, …]] )唯一性约束
唯一性约束是指数据表中的某一个字段值不能有重复的现象。当一个字段(列)被设置了唯一性约束unique时,插入数据将检查该字段的数据合理性。
语法:uniquecreate table table_name ( column_name1 column_type1 unique[, column_name2 column_type2[, …]] )注意:
1.Primary key
约束的字段默认具有唯一性约束。
2.唯一性约束包含NULL
,即当一个字段被设置了唯一性约束的时候,只允许一条记录的该列为NULL
。非空约束
非空约束是指数据表中的某一个字段必须为非NULL
的值,即向表中插入数据时,必须提供非NULL
字段的值,以确保数据能正确添加到表中。
语法:not nullcreate table table_name ( column_name1 column_type1 not null [, column_name2 column_type2[, …]] )默认值约束
默认值约束是指向数据表中添加数据时,具有默认值约束的字段,如果insert
语句未对该字段赋值,则该字段自动以默认值填充。
语法:defaultcreate table table_name ( column_name1 column_type1 default default_value [, column_name2 column_type2[, …]] )唯一约束和主键约束的区别?
1.一张表里只能有一个主键约束,可以有多个唯一约束。
2.唯一性约束所在的列允许空值,但是主键约束所在的列不允许空值。
3.主键列,默认是聚集索引,聚集索引 查询效率最高。
SQL语句的复合查询
复合查询的重点内容有这么三个:
简单连接查询
当需要获取的数据在大于等于两个表的时候,需要使用连接查询。
简单连接的定义:
在
from
子句中使用逗号(“,”)连接多个表的方式叫简单连接。
简单查询的实例:
select s.sid,s.sname,s.age,a.course,a.results from students as s, acievements as a where s.sid = a.sid;
外连接查询
外连接包括左外连接、右外连接和全外连接三种,也可以简称为左连接、右连接和全连接。
左外连接:
left join … on
以左侧表为主表右外连接:
right join … on
以右侧表为主表全外连接:
full join … on
两个表同时全部显示。
实际具体的例子较多,我不在课件里详解,带大家上另外一个网站上学习:
http://www.w3school.com.cn/sql/sql_join.asp
嵌套连接查询(子查询)
在一个SELECT
语句的WHERE
子句或HAVING
子句中嵌套另一个SELECT
语句的查询称为嵌套查询。
嵌套查询通常是在一次查询不能满足条件的前提下使用的,子查询应使用最大范围的收敛方法,以减少外查询对内存的使用量。
实例:
1.查询语文成绩大于85分的学员姓名(同样以学员表和成绩表为例)。
分析:成绩表中存储了学员的成绩信息,但是不包含学员的基本信息(如姓名、年龄等)。
分析结果如下:
(1)先对achievements表进行查询,获取语文成绩大于85的学员学号。
(2)再根据(1)中的学号从student表中获取学员姓名。
2.查询年龄小于21岁的学生的各科成绩
分析:学员表中存储了学生的年龄信息,但是没有存储学员的考试成绩。
分析结果如下:
(1)先从student表中查询年龄小于21岁的学生编号。
(2)再根据学员编号从achievements表中获取成绩信息。
索引
关于这部分,我们的重点是索引的建立、修改及删除
什么是索引
索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结构一道考虑。应用系统的性能直接与索引的合理直接有关。下面给出建立索引的方法和要点。
建立索引
CREATE INDEX命令语法:
CREATE [unique] INDEX [user.]index ON [user.]table (column [ASC | DESC] [,column [ASC | DESC] ] ... ) [CLUSTER [scheam.]cluster] [INITRANS n] [MAXTRANS n] [PCTFREE n] [STORAGE storage] [TABLESPACE tablespace] [NO SORT] Advanced相关解释:
schema
— ORACLE模式,缺省即为当前帐户
index
— 索引名
table
— 创建索引的基表名
column
— 基表中的列名,一个索引最多有16列,long
列、long raw
列不能建索引列
DESC、ASC
— 缺省为ASC即升序排序
CLUSTER
— 指定一个聚簇(Hash cluster不能建索引)
INITRANS、MAXTRANS
— 指定初始和最大事务入口数
Tablespace
— 表空间名
STORAGE
—存储参数,同create table
中的storage
PCTFREE
—索引数据块空闲空间的百分比(不能指定pctused
)
NOSORT
—不(能)排序(存储时就已按升序,所以指出不再排序)- 建立索引的目的:
提高对表的查询速度
对表有关列的取值进行检查。
但是,对表进行insert
,update
,delete
处理时,由于要表的存放位置记录到索引项中而会降低一些速度。
注意:一个基表不能建太多的索引;
空值不能被索引
只有唯一索引才真正提高速度,一般的索引只能提高30%左右。
修改索引
- 语法:
其中:ALTER [UNIQUE] INDEX [user.]index [INITRANS n] [MAXTRANS n] REBUILD [STORAGE n]
REBUILD
是 根据原来的索引结构重新建立索引,实际是删除原来的索引后再重新建立。删除索引
当不需要时可以将索引删除以释放出硬盘空间。 命令如下:
DROP INDEX [schema.]indexname分区
什么是分区表?为什么要分区
当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。
表分区的具体作用
Oracle的表分区功能通过改善可管理性、性能和可用性,从而为各式应用程序带来了极大的好处。通常,分区可以使某些查询以及维护操作的性能大大提高。此外,分区还可以极大简化常见的管理任务,分区是构建千兆字节数据系统或超高可用性系统的关键工具。
表分区的优缺点
优点:
改善查询性能:
对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
增强可用性:
如果表的某个分区出现故障,表在其他分区的数据仍然可用;
维护方便:
如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
均衡I/O:
可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能。
缺点:
已经存在的表没有方法可以直接转化为分区表。不过Oracle 提供了在线重定义表的功能。
表分区的几种类型及操作方法
分区的类型有范围分区,列表分区,散列分区和组合范围散列分区这么几种。
我们主要讲最常用的范围分区:
范围分区将数据基于范围映射到每一个分区,这个范围是你在创建分区时指定的分区键决定的。这种分区方式是最为常用的,并且分区键经常采用日期。**当使用范围分区时,请考虑以下几个规则:** 1、每一个分区都必须有一个`VALUES LESS THEN`子句,它指定了一个不包括在该分区中的上限值。分区键的任何值等于或者大于这个上限值的记录都会被加入到下一个高一些的分区中。2、所有分区,除了第一个,都会有一个隐式的下限值,这个值就是此分区的前一个分区的上限值。
3、在最高的分区中,`MAXVALUE`被定义。`MAXVALUE`代表了一个不确定的值。这个值高于其它分区中的任何分区键的值,也可以理解为高于任何分区中指定的`VALUE LESS THEN`的值,同时包括空值。 **例一:** 假设有一个`CUSTOMER`表,表中有数据`200000`行,我们将此表通过`CUSTOMER_ID`进行分区,每个分区存储`100000`行,我们将每个分区保存到单独的表空间中,这样数据文件就可以跨越多个物理磁盘。下面是创建表和分区的代码,如下:CREATE TABLE CUSTOMER ( CUSTOMER_ID NUMBER NOT NULL PRIMARY KEY, FIRST_NAME VARCHAR2(30) NOT NULL, LAST_NAME VARCHAR2(30) NOT NULL, PHONE VARCHAR2(15) NOT NULL, EMAIL VARCHAR2(80), STATUS CHAR(1) ) PARTITION BY RANGE (CUSTOMER_ID) ( PARTITION CUS_PART1 VALUES LESS THAN (100000) TABLESPACE CUS_TS01, PARTITION CUS_PART2 VALUES LESS THAN (200000) TABLESPACE CUS_TS02 )**例二:按时间划分**CREATE TABLE ORDER_ACTIVITIES ( ORDER_ID NUMBER(7) NOT NULL, ORDER_DATE DATE, TOTAL_AMOUNT NUMBER, CUSTOTMER_ID NUMBER(7), PAID CHAR(1) ) PARTITION BY RANGE (ORDER_DATE) ( PARTITION ORD_ACT_PART01 VALUES LESS THAN (TO_DATE('01- MAY -2003','DD-MON-YYYY')) TABLESPACEORD_TS01, PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE('01-JUN-2003','DD-MON-YYYY')) TABLESPACE ORD_TS02, PARTITION ORD_ACT_PART03 VALUES LESS THAN (TO_DATE('01-JUL-2003','DD-MON-YYYY')) TABLESPACE ORD_TS03 )**例三:MAXVALUE**CREATE TABLE RangeTable ( idd INT PRIMARY KEY , iNAME VARCHAR(10), grade INT ) PARTITION BY RANGE (grade) ( PARTITION part1 VALUES LESS THEN (1000) TABLESPACE Part1_tb, PARTITION part2 VALUES LESS THEN (MAXVALUE) TABLESPACE Part2_tb );删除分区
以下代码删除了P3表分区:
ALTER TABLE SALES DROP PARTITION P3;
在以下代码删除了P4SUB1子分区:ALTER TABLE SALES DROP SUBPARTITION P4SUB1;
注意:如果删除的分区是表中唯一的分区,那么此分区将不能被删除,要想删除此分区,必须删除表。截断分区
截断某个分区是指删除某个分区中的数据,并不会删除分区,也不会删除其它分区中的数据。当表中即使只有一个分区时,也可以截断该分区。通过以下代码截断分区:
ALTER TABLE SALES TRUNCATE PARTITION P2;
通过以下代码截断子分区:ALTER TABLE SALES TRUNCATE SUBPARTITION P2SUB2;





