《MySql必知必会》读书笔记
第一章、了解SQL
1.1、数据库基础
1.1.1、什么是数据库
数据库(database)
保存有组织的数据的容器(通常是一个文件或一组文件)。
数据库软件称为DBMS(数据库管理系统)。数据库是通过DBMS创建和操作的容器。
1.1.2、表
表(table)
某种特定类型数据的结构化清单。
表名
表名的唯一性取决于多个因素,如数据库名和表名等的结合。虽然在相同数据库中不能两次使用相同的表名,但在不同的数据库中却可以使用相同的表名。
模式(schema)
关于数据库和表的布局及特性的信息。
1.1.3、列和数据类型
表由列组成。列中存储着表中某部分的信息。
列(column)
表中的一个字段。所有表都是由一个或多个列组成的。
数据类型
所容许的数据的类型。每个表列都有相应的数据类型,它限制(或容许)该列中存储的数据。
1.1.4、行
表中的数据是按行存储的,所保存的每个记录存储在自己的行内。
行(row)
表中的一个记录。
1.1.5、主键
主键(primary key)
一列(或一组列),其值能够唯一区分表中每个行。
表中的任何列都可以作为主键,只要它满足以下条件:
- 任意两行都不具有相同的主键值;
- 每个行都必须具有一个主键值(主键列不允许NULL值)。
1.2、什么是SQL
SQL是结构化查询语言(Structured Query Language)的缩写。SQL是一种专门用来与数据库通信的语言。
第二章 、MySql简介
2.1、什么是MySQL
MySQL是一种DBMS,即它是一种数据库软件。
第三章、使用MySql
3.2、选择数据库
关键字(key word)
作为MySQL语言组成部分的一个保留字。绝不要用关键字命名一个表或列。
为了使用crashcourse数据库,应输入以下内容:
输入:use crashcourse;
输出:
3.3、了解数据库和表
通过SHOW可以显示数据库中的数据库
输入:SHOW DATABASES;
输出:
分析:SHOW DATABASES;返回可用数据库的一个列表。
为了获得数据库内的表的列表,使用SHOW TABLES;
输入:SHOW TABLES;
输出:
分析:SHOW TABLES;返回当前选择的数据库内可用表的列表。
SHOW也可以用来显示表列:
输入:SHOW COLUMNS FROM customers;
输出:
DESCRIBE语句
MySQL支持用DESCRIBE作为SHOW COLUMNS FROM的一种快捷方式。换句话说,DESCRIBE customers;是SHOW COLUMNS FROM customers;的一种快捷方式。
SHOW STATUS; 用于显示广泛的服务器状态信息;
SHOW CREATE DATABASE;和SHOW CREATE TABLE; 分别用来显示创建特定数据库或表的MySQL语句;
SHOW GRANTS,用来显示授予用户的安全权限;
SHOW ERRORS和SHOW WARNINGS,用来显示服务器错误或警告消息。
第四章、检索数据
4.2、检索单个列
输入:SELECT id from department;
输出:
4.3、检索多个列
在选择多个列时,一定要在列名之间加上逗号,但最后一个列名后不加。
输入:SELECT id,departmentName from department;
输出:
4.4、检索所有列
使用通配符*号
输入:SELECT * FROM department;
4.5、检索不同的行
输入:SELECT DISTINCT id FROM department;
分析:关键字DISTINCT告诉MySQL只返回唯一的id,DISTINCT必须放在列名前。
4.6、限制结果
为了返回第一行或前几行,可使用LIMIT子句。
输入:select gender from employee LIMIT 3;
分析:返回前三行。
如果想返回下一个五行,可指定要检索的开始行和行数,如下所示:
输入:select id from department limit 5,5;
分析:第一个5为开始检索行,第二个5为要检索的行数。
另一种替代语法:
LIMIT 4 OFFSET 3意味着从行3开始取4行,就像LIMIT 3,4一样。
4.7、使用完全限定的表名
输入:
SELECT department.departmentName
from springboot-03-web.department
第五章、排序检索数据
5.1、排序数据
使用关键字ORDER BY
输入:
SELECT departmentName
from department
ORDER BY id;
5.2、按多个列排序
列名之间使用逗号分开
输入:
SELECT id,departmentName
from department
ORDER BY id,departmentName;
分析:仅在多个行具有相同的id时,才会按departmentName进行排序,如果id是唯一的,则不会按departmentName排序。
5.3、指定排序方向
ORDER BY 默认是升序,降序的话需要使用关键字DESC。
输入:
SELECT id,departmentName
from department
ORDER BY id DESC;
在多个列上降序排序
,如果想在多个列上进行降序排序,必须对每个列指定DESC关键字。
与DESC相反的是ASC(升序),但是没太大用处,因为升序是默认的。
使用ORDER BY 和 LIMIT的组合,能够找出一个列中最高或最低的值。下面演示找到id最大的departmentName:
输入:
SELECT id,departmentName
from department
ORDER BY id DESC
LIMIT 1;
输出:
如果使用LIMIT,它必须位于ORDER BY之后。
第六章、过滤数据
6.1、使用WHERE子句
输入:
SELECT id,departmentName
from department
where id=105;
分析:只返回id=105的行。
输出:
WHERE子句的位置
在同时使用ORDER BY 和 WHERE 子句时,应该让ORDER BY位于 WHERE之后,,否则会产生错误。
6.2、WHERE子句操作符
6.2.1、检查单个值
输入:
SELECT id,departmentName
from department
where id=105;
列出id小于105的所有departmentName
输入:
SELECT id,departmentName
from department
where id<105;
输出:
6.2.2、不匹配检查
示例:找不id不等于105的所有
输入:
SELECT id,departmentName
from department
where id<>105;
输出:
何时使用引号
单引号用来限定字符串。如果将值与串类型的列进行比较,则需要限定引号,用来与数值列进行比较的值不用引号。
6.2.3、范围值检查
使用BETWEEN操作符。
输入:
SELECT id,departmentName
from department
where id BETWEEN 102 AND 104;
输出:
6.2.4、空值检查
SELECT语句有一个特殊的WHERE子句,可以用来检查具有NULL值的列。就是 IS NULL子句。
输入:
SELECT id,department
from employee
where department IS NULL;
第七章、数据过滤
7.1、组合WHERE子句
使用AND子句 或 OR子句的方式进行组合。
7.1.1、AND操作符
使用AND给WHERE子句附加条件
输入:
select id, price, name
from produces
where id = 103 and price < 10;
7.1.2、OR操作符
它指示MySQL检索匹配任一条件的行
输入:
select name,price
from produces
where id =102 or id = 103;
7.1.3、计算次序
where可包含任意数目的and和or操作符。
and操作符的优先级高,使用时,我们需要使用圆括号进行区分优先级。
7.2、IN操作符
IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN取合法值的由逗号分开,全部用圆括号括起来。
输入:
SELECT id,department
from employee
where id in (1001,1003)
ORDER BY id;
输出:
7.3、NOT操作符
否定它之后所跟的任何条件。
输入:
SELECT id,department
from employee
where id NOT in (1001,1003)
ORDER BY id;
输出:
MySQL中的NOT
MySQL支持使用NOT对IN、BETWEEN和EXISTS子句取反。
第八章、用通配符进行过滤
8.1、LIKE操作符
**通配符 ** 用来匹配值的一部分的特殊字符。
搜索模式
由字面值、通配符或者两者组合构成的搜索条件。
为在搜索子句中使用通配符,必须使用LIKE操作符。LIKE只是MySQL后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。
8.1.1、百分号(%)通配符
在搜索串中,%表示任何字符出现任意次数。
例如,为了找到所有以词abc开头的产品,可以使用以下语句:
输入:
select id,name
from products
where name like ‘abc%’;
‘%abc%’表示匹配任何位置包含文本abc的值。
‘s%e’表示以s开头,以e结尾。
8.1.2、下划线(_)通配符
下划线与百分号的用途一样,但是下划线只能匹配一个字符。
‘_abc’ 表示搜索第二个到最后字符为abc
8.2、使用通配符的技巧
- 不要过度使用通配符。
- 在确需使用时,除非绝对必要,不在搜索模式开始处使用。
- 注意通配符的位置。
第九章、用正则表达式进行搜索
9.2、使用MySQL正则表达式
正则表达式的作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较。
9.2.1、基本字符匹配
下面的语句检索列name包含文本1000的所有行:
输入:
select name
from products
where name REGEXP ‘1000’
order by name;
REGEXP后所跟的东西作为正则表达式处理。
9.2.2、进行OR匹配
为搜索两个串之一,使用 | , 如下所示:
输入:
select name
from products
where name REGEXP ‘1000|2000’
order by name;
9.2.3、匹配几个字符之一
如果只想匹配特定的字符,可通过指定一组用[和]括起来的字符来完成,如下所示:
输入:
select name
from products
where name REGEXP ‘[123] Ton’
order by name;
分析:这里使用正则表达式[123] Ton。[123]定义一组字符,它的意思是匹配1或匹配2或匹配3。因此 1 ton ,2 ton,3 ton都能返回。
实际上,[]是另一种形式的OR语句。事实上[123]为[1|2|3]的缩写。
字符集合也可以被否定,它将匹配除指定字符外的任何东西。为否定一个字符集,在集合的开始处放置一个^即可。
9.2.4、匹配范围
[0-9]、[a-z]分别表示匹配0-9、a-z任意字符。
9.2.5、匹配特殊字符
为了匹配特殊字符,必须使用\为前导。\-表示查找-,\.表示查找.。
9.2.6、匹配字符类
9.2.7、匹配多个实例
示例:
输入:
分析:sticks?表示匹配stick或sticks,因为?匹配它前面的任何字符0次或1次。
‘[[:digit:]]{4}’ :[:digit:]匹配任意数字,[4]要求前面的字符出现4次,所以连在一起就是匹配连在一起的任意四位数字。
9.2.8、定位符
为了匹配特定位置的文本
^[0-9\\.] 表示只在.或任意数字为串中的第一个字符时才匹配他们。
使REGEXP起类似LIKE的作用 LIKE匹配整个串而REGEXP匹配子串。利用定位符,通过用^开始每个表达式,用$结束每个表达式,可以使REGEXP的作用与LIKE一样。
第十章、创建计算字段
10.1、计算字段
字段(field)
基本上与列(column)的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段通常用在计算字段的连接上。
10.2、拼接字段
拼接(concatenate)
将值联结到一起构成单个值。
在MySQL的select语句中,可使用Concat()函数来拼接两个列。
输入:
SELECT CONCAT(id,’ (‘,department,’)’)
from employee
ORDER BY id;
输出:
分析:Concat()拼接串,即把多个串连接起来形成一个较长的串。’ (‘表示左圆括号,’)’表示右圆括号。
可以使用
RTrim(str)
函数去除值右边的所有空格,使用
LTrim(str)
函数去除值左边的所有空格。
使用别名
别名(alias)是一个字段或值的替换名。别名用AS关键字赋予。也称导出列。
输入:
SELECT CONCAT(id,’ (‘,RTRIM(department),’) ‘) AS dapartment_info
from employee
ORDER BY id;
输出:
10.3、执行算数计算
输入:
SELECT id,
quantity,
price,
quantity*price as expanded_price
from orderitems
输出:
分析:输出的expanded_price列为一个计算字段。
MySQL支持表中列出的基本算数操作符,此外,可用圆括号来区分优先顺序。
第十一章、使用数据处理函数
11.2、使用函数
大多数SQL实现支持以下类型的函数。
- 用于处理文本串的文本函数
- 用于在数值数据上进行算术操作的数值函数
- 用于处理日期和时间值并从这些值中提取特定成分的日期和时间函数。
- 返回DBMS正使用的特殊信息的系统函数。
11.2.1、文本处理函数
上章的RTrim()函数就是一个文本处理函数,这次介绍Upper()函数:
输入:
SELECT id,UPPER(lastName)
from employee
ORDER BY id DESC;
输出:
分析:Upper()函数将文本转换为大写。
常用的文本处理函数:
SOUNDEX()是一个将任何文本串替换为描述其语音表示的字母数字模式的算法。
11.2.2、日期和时间处理函数
MySQL使用的日期格式必须为yyyy-mm-dd。
输入:
SELECT id,department
from employee
where birth = ‘2023-02-06’;
输出:
分析:直接使用where birth = ‘2023-02-06’ 不可靠。比如存储的是2023-02-06 12:21:23, 则where birth = ‘2023-02-06’失败。解决办法是使用Date函数,Date(birth)指示MySQL仅提取列的日期部分,所以更可靠的SQL语句应该为:
SELECT id,department,birth
from employee
where DATE(birth) = ‘2023-02-06’;
如果想检索2023年3月的所有订单:
输入:
select id,num
from orders
where Year(order_date) = 2023 and Month(order_date) = 3;
分析:Year()是一个从日期中返回年份的函数,Month()从日期中返回月份,因此,where Year(order_date) = 2023 and Month(order_date) = 3;检索出order_date为2023年3月的所有行。
11.2.3、数值处理函数
第十二章、汇总数据
12.1、聚集函数
我们经常需要汇总数据而不用把他们实际检索出来,为此MySQL提出了专门的函数。使用这些函数,MySQL查询可用于检索数据,以便分析和报表生成。这种类型的检索例子有以下几种。
- 确定表中行数(或者满足某个条件或包含某个特定值的行数)
- 获得表中行组的和
- 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。
聚集函数(aggregate function)
运行在行组上,计算和返回单个值的函数。
12.1.1、AVG()函数
AVG()通过对表中行数计数并计算特定列值之和,求得该列值的平均值。
下面的例子使用AVG()返回orderitems表中所有产品的平均价格
输入:
select AVG(price) as avg_price
from orderitems;
输出:
AVG()函数也可用来确定特定列或行的平均值。
输入:
select AVG(price) as avg_price
from orderitems
where id in (1,2);
输出:
分析:只输出id=1,id=2两个的平均值。
12.1.2、COUNT()函数
COUNT()函数进行计数。可利用COUNT()确定表中行的数目或符合特定条件的行的数目。
COUNT()函数有两种使用方式。
- 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
- 使用COUNT(column)对特定列中具有值的行进行计数,忽略空值。
输入:
SELECT COUNT(*) as num_employee
from employee;
输出:
分析:利用count(*)对所有行计数,不管行中各列有什么值。
12.1.3、MAX()函数
MAX()返回指定列中的最大值。MAX()要求指定列名。
输入:
SELECT MAX(price) as max_price
from orderitems;
12.1.4、MIN()函数
与MAX()函数功能相反。
12.1.5、SUM()函数
用来指定列值的和(总和)。
输入:
SELECT SUM(price) as sum_price
from orderitems;
输出:
sum()也可以用来合计计算值。
输入:
SELECT SUM(price*quantity) as total_price
from orderitems;
sum()函数忽略列值为NULL的行。
12.2、聚集不同值
以上5个聚集函数都可以如下使用:
- 对所有的行执行计算,指定ALL参数或不给参数(因为ALL是默认的行为);
- 只包含不同的值,指定DISTINCT参数。
12.3、组合聚集函数
SELECT 语句可根据需要包含多个聚集函数:
输入:
SELECT count(*) as num_items,
min(price) as min_price,
MAX(price) as max_price,
AVG(price) as avg_price
from orderitems;
输出:
第十三章、分组数据
13.2、创建分组
分组是在select语句的group by子句中建立的。
输入:
select id,count(*) as num_prods
from products
GROUP BY id;
输出:
分析:GROUP BY子句指示MySQL按id排序并分组数据。可看到1001有2个产品,1002有1个产品,1003有3个产品。
GROUP BY 子句必须出现在WHERE子句之后,ORDER BY子句之前。
使用WITH ROLLUP关键字,可以得到每个分组以及每个分组汇总级别的值,如下所示:
select id,count(*) as num_prods
from products
GROUP BY id WITH ROLLUP;
13.3、过滤分组
HAVING支持所有WHERE操作符。唯一差别就是WHERE过滤行,HAVING过滤分组。
怎样过滤分组?看如下例子:
输入:
select id,count(
) as num_prods
from products
GROUP BY id
HAVING count(
) >= 2;
输出:
13.4、分组和排序
13.5、SELECT子句顺序
第十四章、使用子查询
14.1、子查询
查询(query)
任何SQL语句都是查询。但此术语一般指SELECT语句。
SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。
14.2、利用子查询进行过滤
使用子查询组合上述两个查询:
分析:在SELECT语句中,子查询总是从内向外处理。
相关子查询(correlated subquery)
涉及外部查询的子查询。
第十五章、联结表
15.1、联结
15.1.1、关系表
例如,两张表,一个是vendors,存储供应商信息,另一张表products,存储商品信息。vendors表的主键又被叫做products的外键,它将vendors表与products表关联,利用供应商ID能从ventors表中找出供应商的信息。
外键(foreign key)
外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。
关系数据可以有效地存储和方便地处理。因此,关系数据库的可伸缩性远比非关系数据库要好。
15.2、创建联结
输入:
SELECT name,products,price
from vendors,products
WHERE vendors.id = products.id
ORDER BY name,products;
输出:
分析:from vendors,products列出两个表,他们就是这条SELECT语句联结的两个表的名字,用WHERE子句正确联结。
笛卡尔积(cartesian product)
由没有联结条件的表关系返回的结果为笛卡尔积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
如下所示:
输入:
SELECT name,products,price
from vendors,products
ORDER BY name,products;
输出:
15.2.2、内部联结
目前为止所用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内部联结。使用不同的语法来实现:
输入:
SELECT name,products,price
from vendors INNER JOIN products
ON vendors.id = products.id;
分析:不同点在于from子句,使用INNER JOIN 指出要关联的表名,使用ON关联。
第十六章、创建高级联结
16.1、使用表别名
分析:使用表别名,可以避免因表名太复杂而出错。需要注意的是,表别名只在查询执行中使用。与列别名不同,表别名不返回到客户机。
16.2、使用不同类型的联结
16.2.1、自联结
现在来看使用联结的相同查询:
16.2.2、自然联结
标准的联结返回所有数据,甚至相同的列多次出现。自然联结排除多次出现,使每个列只返回一次。
16.2.3、外部联结
许多联结将一个表中的行与另一个表中的行相关联。但有时会需要包含没有关联行的那些行。联结包含了那些在相关表中没有关联行的行,这种类型的联结称为外部联结。
分析:使用OUTER JOIN 来指定联结的类型。在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。上面的例子使用LEFT OUTER JOIN从from子句的左边表(customers表)中选择所有行。
第十七章、组合查询
17.1、组合查询
MySQL也允许执行多个查询,并将结果作为单个查询结果集返回。这些组合查询通常称为并(union)或复合查询(compound query)。
有两种情况,其中需要使用组合查询:
- 在单个查询中从不同的表返回类似结构的数据;
- 对单个表执行多个查询,按单个查询返回数据。
17.2、创建组合查询
使用UNION操作符来组合数条SQL查询。利用UNION,可给出多条SELECT语句,将它们的结果组合成单个结果集。
17.2.1、使用UNION
union的使用很简单。所需要做的只是给出每条SELECT语句,在各条语句之间放上关键字UNION。
输入:
select id,products,price
from products
where price <= 10
UNION
SELECT id,products,price
from products
where id in (1001,1003);
输出:
分析:UNION指示MySQL执行两条SELECT语句,并把输出组合成单个查询结果集。
17.2.2、UNION规则
- UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分割。
- UNION中的每个查询必须包含相同的列、表达式或聚集函数。
- 列数据类型必须兼容。
17.2.3、包含或取消重复的行
UNION从查询结果集中自动去除了重复的行。这是UNION的默认行为,但是如果需要,可以改变它。事实上,如果想返回所有匹配行,可使用UNION ALL而不是UNION。
17.2.4、对组合查询结果排序
SELECT语句的输出用ORDER BY子句排序。在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。
第十八章、全文本搜索
18.1、理解全文本搜索
并非所有的数据库引擎都支持全文本搜索,两个最常用的引擎为MyISAM和InnoDB,前者支持全文本搜索,后者不支持。
18.2、使用全文本搜索
为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。
在索引之后,SELECT可与Match()和Against()一起使用以实际执行搜索。
18.2.1、启用全文本搜索支持
一般在创建表时启用全文本搜索。使用FULLTEXT子句。
18.2.2、进行全文本搜索
在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式。
分析:由于有两行包含词rabbit,这两个行被返回。
使用完整的Match()说明
传递给Match()的值必须与FULLTEXT()定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)。
18.2.3、使用查询扩展
查询扩展用来设法放宽所返回的全文本搜索结果的范围。使用WITH QUERY EXPANSION。
例如:
18.2.4、布尔文本搜索
以布尔方式,可以提供关于如下内容的细节:
- 要匹配的词;
- 要排斥的词;
- 排列提示;
- 表达式分组;
- 另外一些内容。
即使没有FULLTEXT 索引也可以使用。
第十九章、插入数据
19.1、数据插入
INSERT是用来插入行到数据库表的。插入可以用几种方式使用:
- 插入完整的行;
- 插入行的一部分;
- 插入多行;
- 插入某些查询的结果。
19.2、插入完整的行
输入:
insert into products
VALUES(1002,‘钢铁是怎样炼成的’,20);
编写insert更安全的方法是:
insert into products(id,products,price)
VALUES(1002,‘钢铁是怎样炼成的’,20);
19.3、插入多个行
可以使用多个insert语句,但是过于繁琐,建议使用下面这种方式:
输入:
insert into products(id,products,price)
VALUES(
1002,
‘Linux精通’,
20),
(1004,
‘网络编程’,
28
);
分析:当单条insert语句有多组值,每组值用一对圆括号括起来,用逗号分割。
19.4、插入检索出的数据
insert还可以将一条select语句的结果插入表中。这就是所谓的insert select。
输入:
insert into products(id,products,price)
select id,products,price
from products
where id = 1001;
其实,insert和select中可以不使用相同的列名。例如:
输入:
insert into products(id,products,price)
select id,quantity,price
from orderitems;
输出:
第二十章、更新和删除数据
20.1、更新数据
使用UPDATE。可采用两种方式:
- 更新表中特定行
- 更新表中所有行
UPDATE语句由3部分组成,分别是:
- 要更新的表
- 列名和他们的新值
- 确定要更新行的过滤条件
输入:
UPDATE orderitems
set price = 88
where id = 1;
更新多个列的语法:
UPDATE orderitems
set price = 88,quantity = 2
where id = 1;
当UPDATE语句更新多行时,其中有一行错误,为了继续更新下去,使用IGNORE关键字,如下所示:UPDATE IGNORE orderitems…
为了删除某个列的值,可设置它为NULL(假定表定义允许为空)
20.2、删除数据
使用DELETE。
输入:
DELETE from products
where id = 1;
如果省略了where,将删除所有。
DELETE删除表的内容而不是表本身。
更快的删除 ,如果想从表中删除所有行,可以使用TRUNCATE TABLE语句。
第二十一章、创建和操作表
21.1、创建表
21.1.1、表创建基础
为利用CREATE TABLE创建表,必须给出下列信息:
- 新表的名字,在关键字 CREATE TABLE之后给出;
- 表列的名字和定义,用逗号分割。
21.1.2、使用NULL值
NULL值就是没有值或缺值。允许NULL值的列也允许在插入行时不给出该列的值。不允许NULL值的列不接受该列没有值的行。
21.1.3、主键
主键必须是唯一的。
主键中只能使用不允许NULL值的列。允许NULL值的列不能作为唯一标识。
21.1.4、使用AUTO_INCREMENT
AUTO_INCREMENT告诉MySQL,本列每当增加一行时自动增量。
每个表只允许一个AUTO_INCREMENT列,而且它必须被索引(如,通过使它称为主键)。
21.1.5、指定默认值
默认值用CREATE TABLE语句的列定义中的DEFAULT关键字指定。
输入:
CREATE TABLE os
(
id int NOT NULL,
name char(10) NOT NULL,
quantity int NOT NULL DEFAULT 1
);
分析:在上述例子中,给quantity列的描述添加文本DEFAULT 1指示MySQL,在未给出数量的情况下使用数量1.
21.1.6、引擎类型
ENGINE=INnoDB表示选择INnoDB这个引擎。
21.2、更新表
为更新表定义,可使用ALTER TABLE语句。
为了使用ALTER TABLE更改表结构,必须给出下面的信息:
- 在ALTER TABLE 之后给出要更改的表名;
- 所做更改的列表。
给表添加一个列:
输入:
ALTER TABLE vendors
ADD vend_phone CHAR(20);
删除刚刚添加的列:
输入:
ALTER TABLE vendors
DROP COLUMN vend_phone;
21.3、删除表
使用DROP TABLE语句。
21.4、重命名表
使用
RENAME TABLE
语句可重命名一个表。
输入:
RENAME TABLE products to products1;
第二十二章、使用视图
22.1、视图
视图是虚拟的表,视图只包含使用时动态检索数据的查询。
22.1.1、为什么使用视图
视图的一些常见应用:
- 重用SQL语句
- 简化复杂的SQL操作。在编写查询后,可方便地重用它而不必知道它的基本查询细节。
- 使用表的组成部分而不是整个表。
- 保护数据。
- 更改数据格式和表示。
视图本身不包含数据。
个人理解,视图就是将一个常用语句进行封装,然后下次使用时直接调用视图,不需要再进行一次繁琐的操作,不必了解底层细节。
22.1.2、视图的规则和限制
22.2、使用视图
- 视图用CREATE VIEW语句来创建。
- 使用SHOW CREATE VIEW viewname; 来查看创建视图的语句。
- 用DROP删除视图,其语法为DROP VIEW viewname;。
- 更新视图时,可先用DROP再用CREATE,也可以直接用CREATE OR REPLACE VIEW。
22.2.1、利用视图简化复杂的联结
使用视图进行简化:
22.2.2、用视图重新格式化检索出的数据
使用视图:
22.2.5、更新视图
通常视图是可更新的,但是,如果视图中有以下操作,则不能进行视图的更新:
- 分组(使用GROUP BY 和 HAVING)
- 联结
- 子查询
- 并
- 聚集函数(min()…)
- DISTINCT
- 导出列。
第二十三章、使用存储过程
23.1、存储过程
存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件。
23.3、使用存储过程
23.3.1、执行存储过程
MySQL称存储过程的执行为调用,因此MySQL执行存储过程的语句为CALL。CALL接受存储过程的名字以及需要传递给它的任意参数。
23.3.2、创建存储过程
一个返回产品平均价格的存储过程:
输入:
CREATE PROCEDURE productpricing()
BEGIN
select avg(price) as priceaverage
from produces1;
END;
使用该存储过程
23.3.3、删除存储过程
输入:DROP PROCEDURE productpricing;
分析:productpricing后面没有括号,只给出存储名。
23.3.4、使用参数
一般存储过程并不显示结果,而是把结果返回给你指定的变量。
变量(variable)
内存中一个特定的位置,用来临时存储数据。
调用:
变量名
所有MySQL变量都必须以@开始。
为了显示检索出的产品平均价格,可如下进行:
为了获得3个值,可使用以下语句:
下面是另外一个例子,这次使用IN和OUT参数。ordertotal接受订单号并返回该订单的合计:
输入:
CREATE PROCEDURE ordertotal(
IN onumber INT,
OUT ototal DECIMAL(8,2)
)
BEGIN
select sum(item_price*quantity)
from orderitems
where order_num = onumber
INTO ototal;
END;
23.3.6、检查存储过程
为了显示用来创建一个存储过程的CREATE语句,使用SHOW CREATE PROCEDURE语句。
为了获得包括何时、由谁创建等详细信息的存储过程列表,使用SHOW PROCEDURE STATUS。
第二十四章、使用游标
24.1、游标
游标(cursor)是一个存储在MySQL服务器上的数据库查询,它不是一条select语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览器其中的数据。
只能用于存储过程
24.2、使用游标
步骤:
- 在使用游标前,必须声明(定义)它。
- 一旦声明后,必须打开游标以供使用。
- 对于填有数据的游标,根据需要取出(检索)各行。
- 在结束游标使用时,必须关闭游标。
24.2.1、创建游标
游标用DECLARE语句创建。DECLARE命名游标,并定义相应的SELECT语句,根据需要带WHERE和其他子句。
例如,下面的语句定义了名为ordernumbers的游标,使用了可以检索所有订单的SELECT语句。
CURSOR:游标
24.2.2、打开和关闭游标
游标用OPEN CURSOR语句来打开;
输入:open ordernumbers;
关闭游标
输入:close ordernumbers;
在一个游标关闭后,如果没有重新打开,则不能使用它。但是,使用声明过的游标不需要再次声明,用OPEN语句打开它就可以了。
24.2.3、使用游标数据
在一个游标打开后,可以使用FETCH语句分别访问它的每一行。FETCH指定检索什么数据(所需的列),检索出来的数据存储在什么地方。
第一个例子从游标中检索单个行(第一行):
分析:其中FETCH用来检索当前行的order_num列(将自动从第一行开始)到一个名为o的局部声明的变量中。对检索出的数据不做任何处理。
在下一个例子中,循环检索数据,从第一行到最后一行:
第二十五章、使用触发器
25.1、触发器
需要在某个表发生更改时自动处理,这就是触发器。触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):
- DELETE;
- INSERT;
- UPDATE;
其他MySQL语句不支持触发器。
25.2、创建触发器
在创建触发器时,需要给出4条信息:
- 唯一的触发器名;
- 触发器关联的表;
- 触发器应该响应的活动(DELETE、INSERT或UPDATE);
- 触发器何时执行(处理之前或之后)。
保持每个数据库的触发器名唯一
触发器名必须在每个表中唯一,但不是在每个数据库中唯一。
触发器用CREATE TRIGGER语句创建。
输入:
CREATE TRIGGER newproduct AFTER INSERT ON products
FOR EACH ROW SELECT ‘Product added’;
仅支持表
只有表才支持触发器,视图不支持(临时表也不支持)。
触发器按每个表每个事件每次地定义,每个表每个事件每次只允许一个触发器。每个表最多支持6个触发器。
25.3、删除触发器
使用DROP TRIGGER语句。如下所示:
输入:DROP TRIGGER newproduct;
分析:触发器不能更新或覆盖。为了修改一个触发器,必须先删除它,然后再重新创建。
25.4、使用触发器
25.4.1、INSERT触发器
25.4.2、DELETE触发器
- 在DELETE触发器代码内,可以引用一个名为OLD的虚拟表,访问被删除的行;
- OLD中的值全都是只读的,不能更新。
例子:演示使用OLD保存将要被删除的行到一个存档表中。
25.4.3、UPDATE触发器
- 在UPDATE触发器代码中 ,可以引用一个名为OLD的虚拟表访问以前(UPDATE语句前)的值,引用一个名为NEW的虚拟表访问新更新的值;
- 在BEFORE UPDATE触发器中,NEW中的值可能也被更新(允许更改将要用于UPDATE语句中的值);
- OLD中的值全都是只读的,不能更新。
第二十六章、管理事务处理
26.1、事务处理
事务处理(transaction processing)可以用来维护数据库的完整性,他保证成批的MySQL操作要么完全执行,要么完全不执行。
使用事务和事务处理的一些关键词:
- 事务(transaction) 指一组SQL语句;
- 回退(rollback)指撤销指定SQL语句的过程;
- 提交(commit)指将未存储的SQL语句结果写入数据库表;
- 保留点(savepoint)指事务处理中设置的临时占位符(placeholder),你可以对它发布回退(与回退整个事务处理不同)。
26.2、控制事务处理
管理事务处理的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。
MySQL使用下面的语句来标识事务的开始:
输入:START TRANSACTION
26.2.1、使用ROLLBACK
ROLLBACK命令用来回退(撤销)MySQL语句:
输入:
SELECT * FROM products1;
START TRANSACTION;
DELETE from products1;
SELECT * from products1;
ROLLBACK;
SELECT * from products1;
显然,ROLLBACK只能在一个事务处理内使用。
哪些语句可以回退?
事务处理用来管理INSERT、UPDATE和DELETE语句。不能回退SELECT语句。,不能回退CREATE或DROP操作。
26.2.2、使用COMMIT
在事务的处理中,使用COMMIT语句进行事务的提交。
输入:
START TRANSACTION;
DELETE from products1;
COMMIT;
26.2.3、使用保留点
为了支持回退部分事务处理,必须能在事务处理块中合适的位置放置占位符。这样,如果需要回退,可以回退到某个占位符。
这些占位符称为保留点。为了创建占位符,可以使用SAVEPOINT语句:
输入:SAVEPOINT delete1;
每个保留点都取标识它的唯一名字,以便在回退时,MySQL知道要回退到何处。为了回退到本例给出的保留点,可如下进行:
输入:ROLLBACK TO delete1;
保留点越多越好
因为可以灵活的回退。
释放保留点
使用RELEASE SAVEPOINT明确地释放保留点。
26.2.4、更改默认的提交行为
默认的MySQL行为是自动提交所有更改。要是想让MySQL不自动提交更改,需要使用以下语句:
输入:
SET autocommit=0;
第二十七章、全球化和本地化
第二十八章、安全管理
28.2、管理用户
获得所有用户账号列表,可以使用以下代码:
输入:
USE mysql;
SELECT user from user;
输出:
28.2.1、创建用户账号
为了创建一个新用户账户,使用CREATE USER语句,如下所示:
第二十九章、数据库维护
29.2、进行数据库维护
-
ANALYZE TABLE,用来检查表键是否正确。ANALYZE TABLE返回如下所示的状态信息:
输入:ANALYZE table products1;
输出: