6 索引
索引是存放在模式(schema)中的一个数据库对象,虽然索引总是从属于数据表,但它也和数据表一样属于数据库对象。创建索引的唯一作用就是加速对表的查询,索引通过使用快速路径访问方法来快速定位数据,从而减少了磁盘的I/O。
索引作为数据库对象,在数据字典中独立存放,但不能独立存在,必须属于某个表。
提示:
MySOL使用information_schema数据库里的STATISTICS表来保存该数据库实例中的所有索引信息,用户可通过查询该表来获取该数据库的索引信息。
创建索引有两种方式。
》自动:当在表上定义主键约束、唯一约束和外键约束时,系统会为该数据列自动创建对应的索引。
》手动:用户可以通过create index…语句来创建索引。
删除索引也有两种方式。
》自动:数据表被删除时,该表上的索引自动被删除。
》手动:用户可以通过drop index…语句来删除指定数据表上的指定索引。
索引的作用类似于书的目录,几乎没有一本书没有目录,因此几乎没有一个表没有索引。一个表中可以有多个索引列,每个索引都可用于加速该列的查询速度。
正如书的目录总是根据书的知识点来建立一样——因为读者经常要根据知识点来查阅一本书。类似的,通常为经常需要查询的数据列建立索引,可以在一列或者多列上创建索引。创建索引的语法格式如下:
create index index_ name on table_name (column[, column]...);
下面的索引将会提高对employees表基于last_name字段的查询速度。
create index emp_last name idx on employees (last_name);
也可同时对名列建立索引,SOL语句如下:
# 下面语句为employees 的first_name和last name两列同时建立索引 create index emp_last_name_idx2 on employees (first_name,last_name);
MySQL中删除索引需要指定表,采用如下语法格式:
drop index 索引名 on 表名
如下SQL语句删除了employees表上的emp_last name_idx2索引:
drop index emp_last name_idx2 on employees
有些数据库删除索引时于须指宁表名,因为它们要求建立索引时每个索引都有唯一的名字,所以无须指定表名,例如 Oracle 就采用这种策略。但 MySQL 只要求同一个表内的索引不能同名,所以删除索引时必须指定表名。
索引的好处是可以加速查询。但索引也有如下两个坏处。
》与书的目录类似,当数据表中的记录被添加、删除、修改时,数据库系统需要维护索引,因此有一定的系统开销。
》存储索引信息需要一定的磁盘空间。
7 视图
视图看上去非常像一个数据表,但它不是数据表,因为它并不能存储数据。视图只是一个或多个数据表中数据的逻辑显示。使用视图有如下几个好处。
》可以限制对数据的访问。
》可以使复杂的查询变得简单。
》提供了数据的独立性。
》提供了对相同数据的不同显示。
因为视图只是数据表中数据的逻辑显示——也就是一个查询结果,所以创建视图就是建立视图名和查询语句的关联。创建视图的语法如下:
create or replace view 视图名 as subquery
从上面的语法可以看出,创建、修改视图都可使用上面语法。上面语法的含义是,如果该视图不存 在,则创建视图;如果指定视图名的视图已经存在,则使用新视图替换原有视图。后面的 subquery 就是一个查询语句,这个查询可以非常复杂。
注意:
通过建立视图的语法规则不难看出,所谓视图的本质,其实就是一条被命名的SQL 查询语句。
一旦建立了视图以后,使用该视图与使用数据表就没有什么区别了,但通常只是查询视图数据,不会修改视图里的数据,因为视图本身没有存储数据。
如下SQL语句就创建了一个简单的视图:
create or replace view view_test as select teacher_namne, teacher_pass from teacher_table;
通常不推荐直接改变视图的数据,因为视图并不存储数据,它只是相当于一条命名的查询语句而已。为了强制不允许改变视图的数据,MySQL允许在创建视图时使用with check option子句,使用该子句创建的视图不允许修改,如下所示。
create or replace view view_test as select teacher_name from teacher_table #指定不允许修改该视图的数据 with check option;
注意
大部分数据库都采用with check option来强制不允许修改视图的数提,但Oracle 采用 with read only来强制不允许修改视图的数据。
删除视图使用如下语句:
drop view 视图名
如下SQL语句删除了前面刚刚创建的视图
drop view view_test;
8 DML 语句语法
与 DDL 操作数据库对象不同,DML 主要操作数据表里的数据,使用 DML 可以完成如下三个任务。
》插入新数据。
》修改已有数据。
》删除不需要的数据。
DML语句由insert into、update和delete from三个命令组成
1. insert into语句
insert into用于向指定数据表中插入记录。对于标准的SOL语句而言,每次只能插入一条记录,insert into语句的语法格式如下:
insert into table_name [(column [, column...])] values(value [, value...]);
执行插入操作时,表名后可以用括号列出所有需要插入值的列名,而values后用括号列出对应需要插入的值。
如果省略了表名后面的括号及括号里的列名列表,默认将为所有列都插入值,则需要为每一列都指定一个值。如果既不想在表名后列出列名,又不想为所有列都指定值,则可以为那些无法确定值的列分配null。下面的SQL语句示范了如何向数据表中插入记录。
注意:
只有在数据库中已经成功创建了数据表之后,才可以向数据表中插入记录。下面的SQL语句以前面介绍外键约束时所创建的teacher_table2和student_table2为例来介绍数据插入操作。
在表名后使用括号列出所有需要插入值的列:
insert into teacher_table2(teacher_name) values('xyz');
如果不想在表后用括号列出所有列,则需要为所有列指定值;如果某列的值不能确定,则为该列分配一个null值。
insert into teacher_table2 # 使用null代替主键列的值 isql> selet w frcn tencher_tabled values (null, 'abc');
经过两条插入语们后,可以看到teacher_table2表中的数据如图所示
从图13.9中看到abe记录的主键列的值是2,而不是SOL语句插入的null,因为该主键列是自增长的,系统会自动为该列分配值。
根据前面介绍的外键约束规则:外键列里的值必须是被参照列里己有的值,所以向从表中插入记录之前,通常应该先向主表中插入记录,
否则从表记录的外键列只能为null。现在主表teacher_table2中已有了2条记录,现在可以向从 student_table2中插入记录了,SQL语句如下:
insert into student_table2 #当向外键列里插值时,外键列的值必须是被参照列里已有的值 values (null,'张三',2):
注意:
外键约束保证被参照的记录必须存在,但并不保证必须有被参照记录,即外键列可 以为mull。如果想保证每条从表记录必须存在对应的主表记录,则应使用非空、外键两个约束。
在一些特别的情况下,可以使用带子查询的插入语句,带子查询的插入语句可以一次插入多条记录, SOL语句如下:
insert into student_table2(student name) #使用子查询的值来插入 select teacher_name from teacher table2;
正如上面的SQL语句所示,带子查询的插入语句甚至不要求查询数据的源表和插入数据的目的表是同一个表,它只要求选择出来的数据列和插入目的表的数据列个数相等、数据类型匹配即可。
MySQL甚至提供了一种扩展的语法,通过这种扩展的语法也可以一次插入多条记录。MySQL允 许在values后使用多个括号包含多条记录,表示多条记录的多个括号之间以英文逗号(,)隔开。SOL 语句如下:
insert into teacher_ table2 #同时插入多个值 values (null, "Yeeku"), (null, "Sharfly");
2. update语句
update语句用于修改数据表的记录,每次可以修改多条记录,通过使用where子句限定修改哪些记录。where子句是一个条件表达式,该条件表达式类似于Java语言的if,只有符合该条件的记录才会被 修改。没有where子句则意味着where表达式的值总是true,即该表的所有记录都会被修改。update语句的语法格式如下:
update table name set columnl= valuel[, column2 = value2] [WHERE condition];
使用update语句不仅可以一次修改多条记录,也可以一次修改多列。修改多列都是通过在set关键 字后使用columnl=valuel,column2=value2来实现的,修改多列的值之间以英文逗号(,)隔开。
下面的SQL语句将会把teacher_table2表中所有记录的teacher name列的值都改为孙悟空。
update teacher table2 set teacher_name = '孙悟空';
也可以通过添加where条件来指定只修改特定记录,SQL语句如下:
并只修改teacher_id大于1的记录
update teacher_ table2 set teacher name = '猪八戒 where teacher_id > 1