文章目录
- 第1章 了解SQL
- 第2 章 MySQL简介
- 第3章 使用MySQL
- 第4章 检索数据
- 第5章 排序检索数据
- 第6章 过滤数据
- 第七章 数据过滤
- 第8章 用通配符进行过滤
- 第9章 用正则表达式进行搜索
- 第10章 创建计算字段
- 第11 章 使用数据处理函数
- 第12 章 汇总数据
- 第13章 分组数据
- 第14章 使用子查询
- 第15 章 联结表
- 第16章 创建高级联结
- 第17章 组合查询
- 第18章 全文本搜索
- 第19章 插入数据
- 第20章 更新和删除数据
- 第21章 创建和操纵表
- 第22章 使用视图
- 第23章 使用存储过程
- 第24章 使用游标
- 第25章 使用触发器
- 第26章 管理事务处理
- 第27章 全球化和本土化
- 第28章 安全管理
- 第 29章 数据库维护
- 第30章 改善性能
- 附录
第1章 了解SQL
1.1 数据库基础
- 数据库:保存有组织的数据的容器。
- 数据库管理系统:DBMS
- 表:某种特定类型数据的结构化清单。
- 模式:关于数据库和表的布局及特性的信息。
- 列:表中的一个字段。所有表都是由一个或多个列组成的。
- 数据类型:每个表列都有相应的数据类型,它限制(或容许)该列中存储的数据。
- 行:表中的一个记录。
- 主键:其值能唯一区分表中的每一行。
1.2 什么是SQL
SQL:结构化查询语言(Structured Query Language),是一种专门用来与数据库通信的语言。
SQL由很少的词组成,但却提供了一种从数据库中读写数据的简单有效的方法。
第2 章 MySQL简介
- MySQL是一种DBMS,即它是一种数据库软件。
- MySQL受到的唯一真正的批评是它并不总是支持其他DBMS提供的功能和特性。
第3章 使用MySQL
3.1 连接
为了连接到MySQL,需要以下信息:
- 主机名:如果连接到本地MySQL服务器,为localhost
- 端口:默认为3306端口。
- 用户名:默认为:root
- 用户口令:依照安装时设置。
3.2 使用数据库
- 选择数据库:use 数据库名
- 查看数据库信息:show databases;
- 查看表:show tables;
- 查看表信息:show columns from 表名;
所支持的其他show语句还有: - 显示广泛的服务器状态信息:show status;
- 显示创建特定数据库:show create database;
- 显示创建特定的表:show create table;
- 显示授予用户的安全权限:show grants;
- 显示服务器错误或警告:show errors;show warnings;
第4章 检索数据
4.1 select语句
- 检索单列:select 列名 from 表名;
- 检索多个列:select 列1,列2,列3…form 表名;
- 检索所有列:select * from 表名;
- 检索并计算:select 2014-sage from 表名;#2014-某列。
select Lower(sage) from 表名;#小写列 - 取消重复行,比如产品的分类,不同的产品可能属于同一个分类,从而造成分类多次重复:select distinct 列名 form 表名;
4.2 限制结果
- 使用limit限制返回前几行:select 列名 from 表名 limit 数字;(返回前“数字”行)
- 使用limit限制返回从某行开始的几行:select 列名 form 表名 limit 数1,数2;(返回从数1开始的数2行(不包括开始行))
limit中指定要检索的最大行数,如果没有足够的行,MySQL将只返回它能返回的那么多行。
4.3 使用完全限定的表名
- 完全限定的列名:select 表名.列名 from 表名;
- 完全限定的列名和表名:select 表名.列名 from 数据库.表名;
第5章 排序检索数据
- 按字母顺序排列数据:select prod_name from 表名 order by prod_name;
- 按多个列排序:select 列1,列2… from 表名 order by 列1,列2;(先按列1排序,再按列2排序)
- 指定排序方向:select 列名 from 表名 order by 列1 desc,列2;(asc)对列1降序,列2不排序
- 使用order和limit实现最大或最小值:select 列名 from 表名 order by desc limit 1;(最大值)
第6章 过滤数据
- where:select price from products where price=2.5;
6.2 where 子句操作符
- 检查单个值
(1)select prod_name form 表名 where prod_name=‘fuses’ # 用来将值域串类型的列进行比较,需要用引号。
(2) select prod_price form 表名 where prod_price<10 - 不匹配检查
select prod_id form 表名 where prod_id <> 1003 - 范围值检查
select prod_price form 表名 where prod_price between 5 and 10 - 空值检查
select prod_name form 表名 where prod_price is null
第七章 数据过滤
7.1 组合where子句
- and操作符
select prod_id prod_price form 表名 where prod_id < 10 and prod_price >=1000; - or操作符
select prod_price form 表名 prod_id=10 or prod_id =12; - 计算次序
过滤语句中同时出现and和or时,SQL语言,优先处理and,在处理or。
7.2 in操作
- select prod_id form 表名 where prod_id in (1002,1003); #id为1002和1003的所有产品。
- select prod_id form 表名 where prod_id =1002 or prod_id=1003;与上面效果相同
- 为什么使用in操作
7.3 not操作符
用来否定后跟条件。
- select prod_id form 表名 where prod_id not in (1002,1003)
第8章 用通配符进行过滤
8.1 like操作符
- "%"通配符
(1)select prod_id prod_price form 表名 where prod_name like ‘jet%’;#以jet开头,不管它后面是什么
(2)select prod_id prod_price form 表名 where prod_name like ‘%jet%’;#任何位置包含jet的值。 - “_”通配符
用法和“%”一样,但是只匹配单个字符而不是多个字符。
8.2 使用通配符的技巧
- 不要过度使用通配符。如果其他操作结果相同,选择使用其他操作
- 使用通配符时,除非绝对有必要,否则不要把它们放在搜索模式的开始处。
- 注意通配符的位置。
第9章 用正则表达式进行搜索
9.2 使用MySQL正则表达式
MySQL中的正则表达式匹配不区分大小写。
- 基本字符匹配
(1)select prod_name form 表名 where prod_name regexp '.000’;#“.”表示匹配任意字符,1000,2000都会被匹配。
在本案例中,第一条语句不返回数据,而第二条语句返回一条,原因是:like匹配整个值,如果like后面‘ ’被匹配的值不存在,就不会返回(注意此处并未使用%通配符);regexp在列值内进行匹配,如果regexp后面的‘’被匹配的值存在,就返回相应的列。
regexp也可以匹配整个列值,使用^和$定位符即可。 - 进行or匹配
select prod_name form 表名 where prod_name regexp '1000|2000’ - 匹配几个字符之一
select prod_name form 表名 where prod_name regexp '[123] Ton’;#[123]表示1或2或3;是[1|2|3]的缩写 - 匹配范围
select prod_name form 表名 where prod_name regexp '[1-5] Ton’;#也可以是字母[a-z] - 匹配特殊字符:使用转义字符“\-”:查找"-";“\.”:查找“.”。
- 匹配字符类
- 匹配多个实例
(1)select prod_name form 表名 where prod_name regexp '\\([0-9] sticks?\\)’;#\(匹配),[0-9]中任意数字,sticks?:?匹配前面的s出现0次或1次。
(2)select prod_name form 表名 where prod_name regexp '[[:digit:]]{4}’;#匹配连续的4个数字 - 定位符
(1)表示找出以一个数开始的所有产品:[0-9\.]将在文本的任意位置开始查找匹配。
(2)“^”的双重用法:在集合中表示否定;在串中表示开始位置。
第10章 创建计算字段
10.1 计算字段
- 在上面的每个例子中,存储在表中的数据都不是应用程序所需要的,我们需要直接从数据库中检索出转换、计算或格式化的数据;而不是检索出数据,然后再在客户机应用程序中重新格式化。
- 只有数据库知道select语句中的哪些列是实际的表列,哪些是计算字段。计算字段的数据是以其他列的数据相同的方式返回的。
10.2 拼接字段
- 使用concat()函数:需要一个或多个指定的串,各个串之间使用逗号隔开。
select Concat(vend_name,’(’,vend_country,’)’) from 表名 - select Concat(RTrim(vend_name),’(’,RTrim(vend_country),’)’) from 表名
RTrim():删除右侧多于的空格。 - 使用别名:AS
select Concat(RTrim(vend_name),’(’,RTrim(vend_country),’)’) AS vend_title from 表名
10.3 执行算数计算
select prod_id, quantity,item_price, quantity*item_price AS expanded_price from 表名 where order_num=2005;
第11 章 使用数据处理函数
11.2 使用函数
- 文本处理函数
(1)Upper();将文本转换为大写。
select vend_name,Upper(vend_name) as vend_name_upcase form 表名
(2)常用的文本处理函数
(3)其中Soundex是一个将任何文本串转换为描述其语言表示的字母数字模式的算法。它考虑了类似的发音字符和音节,使得能对串进行发音比较而不是字母比较,
select cust_name,cust_contact from 表名 where Soundex(cust_contact)=Soundex(‘Y Lie’);
- 日期和时间处理函数
(1)常用的日期和时间处理函数
(2)无论是插入还是更新表值等操作,日期必须为格式yyyy-mm-dd。
select cust_id,order_num from 表名 where order_date=‘2005-09-01’;
(3)解决“2005-09-01 11:30:05”不等于“2005-09-01”的情况
解决方法:使用Date():表示仅提取日期部分
select cust_id,order_num from 表名 where Date(order_date)=‘2005-09-01’;
(4)检索2005年9月份的数据
select * from 表名 where Date(order_date) between ‘2005-09-01’ and ‘2005-09-30’;
select * from 表名 where Year(order_date) =2005 and Month(order_date) =9; - 数值处理函数
第12 章 汇总数据
12.1 聚集函数
- avg():只能用来确定特定数值列的平均值;会忽略掉列值为null的行。
select avg(prod_price) as avg_price from 表名 - Count()
(1)Count(*):统计行
(2)Count(列):统计某列的值。 - Max()
max():一般用来找出最大的数值,但MySQL允许它用来返回任意列的最大值。对于文本数据列,Max()返回数据列排序后的最后一行。
Max()也会忽略数据为null的值。
12.2 聚集不同值
- 12.2中的5个聚集函数都可以如下使用:
(1)对所有行执行计算。指定all参数或不指定参数(默认为all)。
(2)只包含不同的值。指定Distinct。 - 举例
select avg(distinct prod_price) as avg_price from 表名
12.3 组合聚集函数
select Count(*) as num__items,Min(prod_price) as price_min,Max(prod_price) as price_max,Avg(prod_price) as price_avg from 表名;
第13章 分组数据
13.2 创建分组
- 分组是在select语句的Group by子句中建立的。
select vend_id Count(*) as num_prods from 表名 Group by vend_id;# 将结果通过vend_id分组。
- 使用Group by的一些规定
13.3 过滤分组
- Having函数:目前为止所有类型的where子句都可以用having来代替,唯一的差别是,where过滤行,having过滤分组。
select cust_id, Count(*) as orders from 表名 Group by cust_id Having Count( * )>=2; - where和having同时运用
select vend_id, Count(*) as num_prods from 表名 where prod_price>=10 Group by vend_id Having Count( * )>=2;# 具有两个以上、价格大于10的产品。
13.4 分组和排序
13.5 select子句顺序
select语句中使用时必须遵循的次序。
第14章 使用子查询
本章的查询必须使用MySQL4.1之后的版本。
14.1 子查询
子查询:嵌套在其他查询中的查询。
14.2 利用子查询进行过滤
实际需求:需要列出订购物品TNT2的所有客户,可以:
(1)检索包含物品TNT2的所有订单的编号
(2)检索具有前一步列出的订单编号的所有客户。
(3)检索前一步返回的所有客户ID的客户信息。
上述的每个步骤,都可以单独作为一个查询来执行,可以把一条select语句返回结果作为另一个select语句的where条件。
14.3 作为计算字段使用子查询
使用子查询的另一种方法。
假如需要显示customers表中每个客户的订单总数。订单与相应的客户ID存储在orders表中。
(1)从customers表中检索客户列表。
(2)对于检索出的每个客户,统计在orders表中的订单数目。
14.4 相关子查询
相关子查询:涉及外部查询的子查询。
任何时候,只要类名可能有多义性,就必须使用这种查询。
这样的结果是不正确的,原因是:
第15 章 联结表
15.1 联结
1 关系表
(1)外键:某个表中的一列,它是另一个表的主键。
(2)可伸缩性:能够适应不断增加的工作量而不失败。
2. 联结的作用
15.2 创建联结
- 操作:规定要联结的表以及他们如何关联即可。
select vend_name, prod_name,prod_price from vendors,products where vendors.vend_id=products.vend_id;#
可以看出,在表products中,vend_id便是外键。 - where子句的重要性
where子句作为过滤条件,它只包含那些匹配给定的条件(这里是联结条件)的行。没有where子句,第一个表中的每个行将与第二个表中的每个行匹配,而不管逻辑上他们是否可以配置在一起。 - 笛卡尔积:由没有联结条件的表关系返回的结果。检索出的行的数目=第一个表中行数*第二个表中行数。
select vend_name, prod_name,prod_price from vendors,products;
- 内部联结:目前为止,所用的联结称为等值联结,它基于两个表之间的相等测试。这种联结也称为内部联结。
上面的语句还可以用下面的语句来代替:
- 联结多个表
(1)SQL对一条select语句中可以联结的表的数目没有限制。
(2)正如14.3.2 中子查询,可以用以下的关联查询代替
第16章 创建高级联结
16.1 使用表别名
- 给列取别名:
- 给表取别名
16.2 使用不同类型的联结
- 自联结
情景:发现某商品(ID为DINTR)存在问题,想知道生产该物品的供应商是否也存在这些问题,次查询要先查到该商品的供应商,然后再找出这个供应商生产的产品。
(1)方案1:使用子查询
(2)方案2:使用联结
PS:用自联结不用子查询
自联结通常作为外部语言来代替从相同表中检索数据时使用的子查询语句,虽然处理结果相同,但处理联结比处理子查询要快得多。 - 自然联结
无论何时对表进行联结,应该至少有一个列出现在不止一个表中(被联结的列),标准的联结返回所有的数据,甚至相同的列出现多次,自然联结排除多次出现,使每个列只返回一次。
系统如何完成该工作呢?答案是:系统并不完成这项工作,这是由程序员完成。
自然联结中,你只能选择那些唯一的列,这一般是通过通配符**(select *),对所有其他列使用明确的子集**来完成的。
- 外部联结
(1)许多联结将一个表中的行与另一个表中的行相关联。但有时候会需要包含没有关联行的那些行。
(2)外部联结:联结中包含了那些在相关表中没有关联行的行。
(3)外部联结:
与内部联结不同的是,外部联结还包括没有关联的行,在使用outer join语法时,必须使用right或left关键字指定其所有行的表(right表示是outer join右边的表;left表示的是outer join左边的表)。
(4)外部联结的类型
外部联结分为左外部联结和右外部联结,它们之间唯一的差别在于所关联的表的顺序不同(左外部联结可通过颠倒from或where子句中表的顺序来转化成右外部联结。因此,两种类型的外部联结可互为调用,究竟使用哪一种,视情况而定)。
16.3 使用带聚集函数的联结
情景:要检索所有客户及每个客户说下的订单。
方式一:使用count():
方式二:使用聚集函数
这个例子使用左外部联结来包含左右客户,甚至包含那些没有下任何订单的客户。
16.4 使用联结和联结条件
16.5 补充
数据库系统概论第五版(王珊)-基础篇(三)第三章
- 等值联结与非等值连接
连接查询的where子句中用来连接两个表的条件叫做连接条件或连接谓词,一般格式为:
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>或
[<表名1>.]<列名1> between [<表名2>.]<列名2> and [<表名2>.]<列名3>
当连接运算符为“=”时,为等值连接,否则为非等值连接。
第17章 组合查询
17.1 组合查询
- 需要组合查询的情况
(1)在单个查询中从不同的表返回类似结构的数据。
(2)对单个表执行多个查询,按单个查询返回数据。 - 组合查询和多个where条件
多数条件下,组合相同表两个查询完成的工作与具有多个where子句条件的单条查询完成的工作相同。
17.2 创建组合查询
- 使用union:在各条语句之间放上关键字union
(1)单行查询
(2)使用union将多个语句组合
(3)使用多条件查询
2. union规则
“合并”是非常容易操作的,但是进行“合并”如要注意以下几条规则。
(1)union必须由两条或两条以上的select语句组成,语句之间使用union关键字分隔。
(2)union中的每个查询必须包含相同的列、表达式或聚集函数
(3)列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含的转换类型(例如,不同的数值类型或不同的日期类型)。
3. 包含或取消重复的行
(1)在17.2.1中,单条语句执行时,第一条返回了4行结果,第二条返回了5行,而使用union组合两条select语句后,只返回了8行,而不是9行。union从查询结果集中自动去除了重复行。
(2)这是union默认的行,如果需要可以使用union all匹配所有行。
4. 对组合查询结果排序
在union组合查询时,只能使用一条order by子句,它必须出现在最后一条select语句之后。
第18章 全文本搜索
18.1 理解全文本搜索
- 并非所有引擎都支持全文本搜索。
- like关键字和正则表达式的限制
(1)性能:通常要求MySQL常识匹配表中所有行,由于被搜索行不断增加,这些搜索可能十分费时。
(2)明确控制:使用通配符和正则表达式很难明确的控制匹配什么,不匹配什么
(3)智能化结果:不提供一种智能化的选择结果。
8.2 使用全文本搜索
18.2.1 启用全文本搜索支持
一般在创建表时启用全文本搜索。它给出被索引列的一个逗号分隔的列表。
不要在导入数据时使用fulltext。
18.2.2 进行全文本搜索
- 使用Match()和Against()执行全文本搜索。Match()指定被搜索的列,Against()指定要使用的搜索表达式。
(1) 传递给Match()的值必须与FULLTEXT()中定义的相同。
(2) 搜索不区分大小写,除非使用binary方式。
- 排序多个搜索项
如果指定多个搜索项,则包含多数匹配词的那些行将具有比 包含较少词的那些行 高的等级值。
18.2.3 使用查询扩展
- 作用:用来设法放宽所返回的全文本搜索结果的范围。
- 使用插叙扩展时,MySQL对数据和索引进行两遍扫描来完成搜索
(1)首先:进行一个基本的全文本搜索,找出与搜索条件匹配的所有行。
(2)其次:MySQL检查这些匹配行并选择所有有用的词。
(3)最后:MySQL会进行再次进行全文本搜索,这次不仅使用原来的条件,而且还使用所有有用的词。
18.2.4 布尔文本搜索
即使没有fulltext,布尔文本搜索也可以用。
- 以布尔方式,可以提供关于如下内容的细节:
(1)要比配的词;
(2)要排斥的词(如果某行不包括这个词,则不返回该行,即使它包含其他指定的词也是如此)
(3)排列提示(指定某些词比其他词更重要(等级更高))
(4)表达式分组
(5)另外的内容。 - 示例:
(1)包含heavy但不包含rope的开始的词的行
(2)rabbit 和 bait 至少包含一个
- 全文本布尔操作符
18.2.5 全文本搜索的使用说明
- 在索引全文本数据时,短词**(具有3个或3个一下的词)**被忽略且从索引中排除。
- MySQL具有内建非用词列表,这些词在索引全文本数据时会被忽略。
- 许多词的出现频率很高,索引它们没有用处。
- 如果表中行数少于3行,全文本搜索不返回结果。
- 忽略词中的单引号,如don’t。
- 不具有词分隔符的语言(包括日语和汉语)不能恰当的返回全文本搜索结果。
- 没有临近操作符。
第19章 插入数据
19.1 数据插入
插入可以有以下几种方式使用
- 插入完成的行
- 插入行的一部分
- 插入多行
- 插入某些查询的结果
19.2 插入完整的行
- 指定表名和被插入到新行中的值。
- 给出列名插入完整行(建议使用此方式,因为使用列的列表能使SQL代码更好的发挥作用,即使表结构发生变化)
- 省略列:
省略列必须满足以下几个条件:
(1)该列定义为null(无值或空值)。
(2)在表定义中给出了默认值。
19.3 插入多个行
每个值用()括起来,多个值之间用“,”隔开。
19.4 插入检索出的数据
将一条select语句的结果插入表中,即insert select。
下例将从表“custnew”中查询到的结果插入到表“customers”中。
这个例子在insert 和select语句中使用了相同的列名,这没有关系,
第20章 更新和删除数据
20.1 更新数据
- 更新数据
- 在update中使用子查询
update语句中可以使用子查询,使得能用select语句检索出的数据更新列数据。 - ignore关键字
在使用update语句更新多行时,如果出现一个错误,则整个update操作就被取消,为了使即使发生错误也会继续更新,可以使用ignore,如下:
update ignore customers…
20.2 删除数据
- 删除一行
删除了表中的数据,但表仍在。
- 更快的删除
删除所有行:使用truncate table。
原理:删除原来的表,然后再新建一个表。
20.3 更新和删除的指导原则
第21章 创建和操纵表
21.1 创建表
- 创建表
- 使用null值
null值就是没有值或者缺值,允许null值的列也允许在插入行时不给出该列值,不允许null值的列,不接受该列没有值的行。 - 主键
(1)单个列,如果是唯一的,则可以作为主键,
(2)如果多个列的组合也是唯一的,同样可以作为主键。
- 使用auto_increment
(1)覆盖auto_increment:当手动插入一个值(它必须是唯一的)时,该值将被用来替代自动生成的值,后续的增量将开始使用该手工插入的值。
(2)确定auto_increment:使用select last_insert_id(),该函数返回最后一个auto_increment值,然后可以将它用于后续的MySQL语句。 - 指定默认值
(1)不允许函数作为默认值,只支持常量
(2)使用默认值而不是null,
21.2 更新表
- 语法:alert table 表名 内容
21.3 删除表
drop table 表名
21.4 重命名表
(1)重命名单个表:rename table 原表名 to 新表名;
(2)重命名多个表:
第22章 使用视图
22.1 视图
- 本章内容适用于MySQL5及以后版本。
- 视图是一个虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
数据库中只存放视图的定义,而不存放视图对应的数据,这些数据存放在原来的基本表中。所以一旦基本表中数据发生变化,则视图中查询的数据也就随之改变。
视图一经定义,也可以被查询、删除。也可以在一个视图之上再定义一个新的视图。 - 参考第15章的例子
(1)此查询必须理解相关表结构,并且知道如何创建查询和对表进行联结。当检索条件发生改变时,必须改变where的内容。
(2)假设将整个查询包装成一个名为productcustomers 的虚拟表,则可以如下轻松检索出相同数据。
这就是视图的作用,productcustomers就是一个视图,作为视图,它不包含表中应该有的任何列或数据,它包含的是一个SQL查询(与上面以正确联结表的相同的查询)
21.1.1 为什么使用视图
- 视图的应用
在视图创建之后,可以用与表基本相同的方式利用它们。可以对视图执行SELECT操作,过滤和排序数据,将视图联结到其他视图或表,甚至能添加和更新数据(添加和更新数据存在某些限制。关于这个内容稍后还要做进一步的介绍)。
重要的是知道视图仅仅是用来查看存储在别处的数据的一种设施视图本身不包含数据,因此它们返回的数据是从其他表中检索出来的。在添加或更改这些表中的数据时,视图将返回改变过的数据。 - 视图的作用
(1)简化用户操作
(2)使用户能以多种角度看待同一数据。
(3)对重构数据库提供了一定程度的逻辑独立性。
(4)对机密数据提供安全保护。
(5)可以更清晰的表达查询。
21.1.2 视图的规则和限制
视图创建和使用的一些规则和限制。
22.2 使用视图
- 视图的创建
(1)子查询可以是任意的select语句,是否可以包含order by子句和distinct短语,则取决于具体系统的实现。
(2)with check option:表示对视图进行update、insert和delete操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。
(3)组成视图的属性列名或者全部省略或者全部指定,没有第三种选择。如果省略了视图的各个属性列名,则隐含该视图由子查询中select子句目标列中的诸字段组成。但在以下三种情况下必须明确指定组成视图的所有列名。
22.2.1 利用视图简化复杂的联结
使用视图最常见的应用之一是隐藏复杂的SQL,这通常都会涉及联结。
这条语句创建了一个名为productcustomers的视图,它联结三个表,以返回已订购了任意产品的所有客户的列表。
为检索出订购了产品名为“TNT2”的客户,可以
22.2.2 用视图重新格式化检索出的数据
以下select语句在单个组合计算列中返回供应商名和位置(第10章):
- 将次语句转化为视图便是:
- 关系数据库管理系统执行create view语句的结果只是把视图的定义存入数据字典,**并不执行其中的select语句。**只是在对视图查询时,才按视图的定义从基本表中将数据查询。
为了检索出以创建所有邮件标签的数据,可以
3. 建立信息系学生视图,并要求进行修改和插入操作时,仍需保证该视图只有信息系的学生。
with check option子句表示:以后对该视图进行插入、修改和删除操作时,关系数据库管理系统会自动加上Sdept='IS’的条件
4. 若一个视图是从单个基本表导出的,并且只是去掉了基本表中的某些行或某些列,但保留了主码,则称这类视图为行列子集视图。
5. 视图不仅可以建立在单个表上,也可以建立在多个表上。
6. 视图还可以建立在一个或多个已经定义好的视图之上。
create view IS_S2
as
select Sno,Sname,Grade
from IS_S1
where Grade>=90;
这里的IS_S2就是建立在IS_S21上的。
22.2.3 用视图过滤不想要的数据
定义一个视图,过滤没有电子邮件地址的客户。
然后就可以使用此视图:
PS:如果从视图检索数据时使用了一条where子句,则两组子句(一组视图中,一组传递给视图的)将自动组合。
22.2.4 使用视图与计算字段
- 表中一般只存储基本数据,由基本数据经过各种计算得到的数据一般不存储。由于视图中的数据并不实际存储,所以定义视图时可以设置一些经过计算得到的派生的属性列,这里列称为虚拟列,带虚拟列的视图也称为带表达式的视图。
视图对于简化计算字段的使用特别有用。
下例(来自第10章)用以:检索某个特定订单中的物品,计算每个物品的总价格。
为此定义一个视图:
然后使用该视图:
22.2.5 分组视图
用带有聚集函数和group by子句的查询来定义的视图。
create view S_G(Sno,Gavg)
as
select Sno,AVG(Grade)
from SC
Group by Sno
22.2.6 删除视图
drop view<view>[cascade];
- 视图删除后视图的定义将从数据字典中删除,如果该视图上还导出了其他视图,则使用cascade级联删除语句把该视图和由它导出的所有视图一起删除。
- 基本表删除后,由该基本表导出的所有视图均无法使用,但是视图的定义没有从字典中清除,删除这些定义需要显示的使用drop view语句。
22.2.7 查询视图
- 与基本表的查询一样。
select Sno,Sage
from IS_Student
where Sage<20
关系数据库管理系统执行对视图的查询时, 首先进行有效性检查,检查查询中涉及的表、 视图等是否存在。如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来, 转换成等价的对基本表的查询,然后再执行修正了的查询。这一转换过程称为视图消解(view resolution).
本例转换后的查询语句为:
select Sno,Sage
from IS_Student
where Sdept='IS' and Sage<20;
- 目前多数关系数据库系统对行列子集视图的查询均能进行正确转换。但对非行列子集视图的查询就不一定能做转换了,因此这类查询应该直接对基本表进行。(补充数据库系统概论第五版(王珊)P123,不甚理解)
- 定义视图并查询视图与基于派生表的查询是有区别的,视图一旦定义,其定义将永久保存在数据字典中,之后所有的查询都可以引用该视图,而派生表只是在语句执行时临时定义,语句执行后该定义即被删除。
22.2.8 更新视图
- 视图是可更新的(即,对其使用insert、update、delete),更新一个视图将更新其基表(对视图的增加或删除行,实际是对其基表增加或删除行)。
- 由于视图是不实际存储数据的虚表, 因此对视图的更新最终要转换为对基本表的更新。像查询视图那样,对视图的更新操作也是通过视图消解,转换为对基本表的更新操作。
update IS_Student
set Sname=‘刘晨’
where Sno=‘201215122’
insert into IS_Student
values(‘201215129’,'赵信',20)
delete from IS_Student
where Sno=‘201215129’
- 为防止用户通过视图对数据进行增加、删除、修改时,有意无意地对不属于视图范围内的基本表数据进行操作,可在定义视图时加上WITH CHECKOPTION子句。这样在视图上增、删、改数据时,关系数据库管理系统会检查视图定义中的条件,若不满足条件则拒绝执行该操作
- 一些情况下,视图是不可更新的。
如果视图中有以下操作,则视图不可更新:
第23章 使用存储过程
23.1 存储过程
- 需要MySQL5版本。
- 之前我们使用的都是针对一个或多个表的单条语句。经常会有一个完整的操作需要多条语句才能完成:
创建存储过程,就是为了以后的使用而保存的一条或多条MySQL语句的集合。可以将其视为批文件,虽然他们的作用不仅仅限于批处理。
23.2 为什么要用存储过程
23.3 使用存储过程
23.3.1 执行存储过程
MySQL称存储过程的执行为调用,因此MySQL执行存储过程的语句为:call。call接收存储过程的名字以及需要传递给它的任意参数。
23.3.2 创建存储过程
创建一个返回产品平均价格的存储过程:
使用该存储:
23.3.3 删除存储过程
23.3.4 使用参数
- productpricing只是一个简单的存储过程,它简单的显示select语句的结果。一般存储过程并不显示结果,而是把结果返回给你指定的变量。
- 以下是productpricing的修改版本(如果不嫌删除此存储过程,则不能再次创建它)
分析:此存储过程接收3个参数,p1存储产品最低价格,ph存储产品最高价格,pa存储产品平均价格。每个参数都必须具有指定类型(此处为decimal(十进制)) - 调用修改后的productpricing:
调用时,这条语句不显示任何数据,它返回以后可以显示的变量。
为了显示检索出的平均价格,可如下进行:
- 使用in和out参数,ordertotal接受订单号并返回。
为了调用这个存储过程,执行以下语句:
显示结果:
23.3.5 建立智能存储过程
(1)目前为止,所用到的存储过程基本上都是封装MySQL简单的select语句,虽然他们全部都是有效的存储过程例子,但他们所完成的工作可以直接用这些封装的语句完成。当在存储过程中包含业务规则和智能处理时,他们的威力才真正显示出来。
(2)添加一个参数taxable,是一个布尔值;select语句发生了改变,将结果存储到total而不是ototal;if语句检查taxable是否为真,如果为真,则用另一组select语句增加营业税到局部变量total。
(3)使用此存储
23.3.6 检查存储过程
显示用来创建一个存储过程的create语句,
show create procedure name
第24章 使用游标
24.1 游标
- 需要MySQL5.
- 使用游标的原因:此前使用的select语句无法实现:
(1)得到第一行,下一行或前一行
(2)不能每次一行地处理所有行
(3)不能在检索出来的行中前进或后退一行或多行。 - 游标不是一条select语句,而是一个存储在MySQL上服务器上的数据库查询。在存储游标之后,应用程序可以根据需要滚动或浏览其中的数据。
- 只能用于存储过程。
24.2 使用游标
使用游标的几个步骤:
1 创建游标:使用declare语句创建游标。
2. 打开和关闭游标
修改后的语句
3. 使用游标数据
使用fetch语句分别访问它的每一行,fetch指定检索什么数据(所需的列),检索出来的数据存储在什么地方,还可以向前移动游标中的内部行指针,使下一条fetch语句检索下一行。
(1)使用fetch检索当前行的order_num列到一个名为o的局部变量中,对检索出来的数据不做任何处理。
(2)循环检索数据,从第一行到最后一行
4. 综合案例
(1)分析:在这个案例中,我们增加了一个名为t的变量,
此存储过程还在运行中创建了一个新表ordertotals,这个表将保存存储过程生成的结果
fetch像以前一样取每个order_num,然后用call执行另一个存储过程,来计算每个订单的合计,
最后,用insert保存每个订单的订单号和合计。
(2)此存储过程不返回数据,但是它创建和填充了一个表,
(3)查看该表
第25章 使用触发器
25.1 触发器
- 需要MySQL5.
- 解决:某条语句在事件发生时自动执行。
- 触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于begin和end语句之间的一组语句):
delete;insert;update;
其他MySQL语句不支持触发器。
25.2 创建触发器
- 创建触发器是,需要给出的4条信息:
- 触发器用create trigger语句创建,
(1)for each row表示代码对每个插入行都执行。
(2)使用insert语句添加一行或多行到products表中,对每个成功的插入,都会显示“product added”信息。 - 仅支持表:只有表才支持触发器。
- 触发器按每个表每个事件每次地定义,每个表每个事件每次只允许一个触发器,因此每个表最多支持6个触发器(每条insert、update、delete的之前和之后)。
单一触发器不能与多个事件或多个表关联,因此,如果你需要一个对insert和update操作执行的触发器,则应该定义两个触发器。
25.3 删除触发器
drop trigger 触发器名。
25.4 使用触发器
- insert触发器:在insert语句执行之前或之后执行,使用此触发器需要知道的几点:
示例:对于auto_increment列进行赋值:
- delete触发器:在delete语句执行之前或之后,
PS:原书缺页
第26章 管理事务处理
26.1 事物处理
- 事物处理可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么不执行。
- 尤其对于关联表,主表发生变化,从表可以不发生变化,但从表发生变化,主表则一定要发生变化,此时,一次主从表发生变化的操作便可以处理成一个事物。
- 事务(transaction):指一组SQL语句。
- 回退(rollback):指撤销指定SQL语句的过程。
- 提交(commit):将未存储的SQL语句结果写入数据库表。
- 保留点(savepoint):事务处理中设置的临时占位符,可以对它发布回退(与整个事务的回退处理不同)。
26.2 控制事物处理
- 事务开始:start transaction
- 使用rollback:rollback只能在一个事务处理的内部使用。
哪些语句可以回退?insert、update和delete语句可以回退,
select语句是不能回退的;另外create和drop操作不能回退,事务处理块中可以使用这两条语句,但如果执行回退,他们不会被撤销。
分析:
- 使用commit
(1)隐含提交:提交(写或保存)操作是自动进行的。
(2)在事务中,提交不会隐含进行,需要commit进行提交。
分析:上例从系统中完全删除订单20010,因为涉及更新两个表中的数据,因此使用事物来处理,保证订单被完全删除。
最后的commit语句仅在两个delete都成功时才会写出更改,如果其中一条delete不起作用,则commit就不会起作用 (实际上它是被自动撤销的)。 - 隐函事物关闭
当commit或rollback语句执行后,事物会自动关闭。 - 使用保留点
(1)简单的rollback和commit语句就可以写入或撤销整个事物处理,但是,只是对简单的事务处理才这样做,更复杂的事务处理可能需要部分提交或回退。
(2)为了支持回退部分食物处理,必须能在事务处理块中合适位置**放置占位符,**这样如果需要回退,可以回退到某个占位符。这些占位符就是保留点。
(3)创建保留点:savepoint 保留点;
(4)使用保留点:rollback to 保留点;
(5)释放保留点:保留点在事务处理完成自动释放。
PS:保留点越多越好,因为保留点越多,就可以越按照自己的意愿灵活的进行回退。 - 更改默认的提交行为
默认的MySQL行为是自动提交所有更改,即执行一条MySQL语句,该语句实际上就会立即生效,为指定MySQL不自动提交,我们可以:
set autocommit=0;
第27章 全球化和本土化
27.1 字符集和校对顺序
MySQL需要摄影不同的字符集、排序方法和检索数据方法。
- 字符集:字母和符号的集合。
- 编码:某个字符集成员的内部表示。
- 校对:为规定字符如何比较的指令。
在MySQL正常的数据库活动(select、insert等)中,不需要操心太多的东西,使用何种字符集和校对的决定在服务器、数据库和表级进行。
27.2 使用字符集和校对顺序
- 查看MySQL支持的字符集列表:show character set;
- 查看MySQL支持校对的完整类表:show collation;# 所有的字符集具有不止一种校对。
- 系统管理在安装时定义一个默认的字符集和校对。此外,也可以在创建数据库时,指定默认的字符集和校对。
确定所用的字符集:show variable like ‘character%’;
确定所用的校对:show variable like ‘collation%’; - 字符集和少是服务器范围(甚至是数据库范围)的设置,不同的表,甚至不同的列都有可能使用不同的字符集,而且两者都可以在创建表时指定。
下例给出了创建表时指定字符集和校对:
- 一般MySQL使用如下确定使用什么样的字符集和校对。
- MySQL允许对每个列设置他们
- 校对在对用order by子句检索出来的数据进行排序时十分重要,如果需要在建表时创建不同的校对顺序排序特定的select语句,可以在select语句自身中进行。
- 除了在order by中使用collate外,还可以在group by、having、聚集函数、别名等情况下使用。
第28章 安全管理
28.1 访问控制
- MySQL服务的安全基础是:用户应该对他们需要的数据具有适当的访问权,既不能多也不能少。
- 防止无意的错误
访问控制不仅仅是防止用户的恶意企图,数据梦魇更为常见的是无意识错误的结果。 - 不要使用root
仅在绝对必要时使用它。
28.2 管理用户
MySQL用户账号和信息存储在名为mysql或MySQL数据库中,需要获得所有账户列表时,可以使用:
28.2.1 创建用户账号
- 创建一个用户:create user 用户名 identified by ‘p@$$word’
- 指定散列口令:
identified by:指定的口令为纯文本,MySQL将在保存到user表之前对其进行加密,为了作为散列值指定口令,使用identified by password - 使用grant或insert
grant语句也可以创建用户账号,但一般来说create user是最清楚最简单的句子, - 重命名一个用户
rename user 原用户名 to 新用户名
28.2.2 删除用户
drop user 用户名
28.2.3 设置访问权限
- 查看用户的权限:show grants for 用户;
- 设置权限使用grant语句,grant语句必须包括:要授予的权限、被授予访问权限的数据库或表、用户名。
给 bforta这个用户针对数据库“crashcourse” "select”的权限。 - grant的反操作为revoke:用来撤销特定的权限
- grant和revoke可在几个层面上控制访问权限
- 可以授予或撤销的每个权限
28.2.4 更改口令
- 使用set password,新口令必须进行如下加密:
- set password还可以用来设置自己的口令
第 29章 数据库维护
29.1 备份数据
MySQL的数据也必须经常备份,由于MySQL数据库是基于磁盘的文件,普通的备份系统和例程就能备份MySQL的数据,但是由于有些文件总是处于打开和使用状态,普通的文件副本备份不一定总是有效。
29.2 进行数据库维护
- analyze table:检查表键是否正确。
- check table:针对许多问题对表进行检查:在MyIsam表上还对索引进行检查
- changed:检查自最后一次检查以来改动过的表;
- extended:执行最彻底的检查;
- fast:只检查未正常关闭的表;
- medium:检查所有被删除的链接并进行键检验
- quick:进行快速扫描
29.3 诊断启动问题
- 服务器启动问题通常在对MySQL配置或服务器本身进行更改时出现。MySQL在这个问题发生时报告错误,但由于多数MySQL服务器是作为系统进程或服务自动启动的,因此这些消息通常看不到。
- 在排除系统启动问题时,首先应尽量考虑手动启动服务器。MySQL服务器本身通过在命令行上执行mysql启动。
- 几个重要的mysqld命令行选项:
29.4 查看日志文件
在使用日志时,可以使用flush logs语句来刷新和重新开始所有的日志文件。
主要的日志文件:
第30章 改善性能
在诊断应用的滞缓现象和性能问题时,性能不良的数据库(以及数据库查询)通常是最常见的祸因。
附录
- 数据库类型
(1)串数据类型
(2)数值数据类型
(3)日期和时间数据类型
(4)二进制数据类型