目录[-]

MYSQL必知必会(Teach Yourself SQL in 10 Minutes)

https://cdn.mysql.com//Downloads/MySQLInstaller/mysql-installer-community-5.7.25.0.msi Mysql安装包

创建第6章节开始起的

第一章 了解数据库

1.1.1 什么是数据库(database)

 

数据库是一个以某种有组织的方式存储的数据集合,使用它的是数据库软件DBMS(数据库管理系统)。

Create Datase lesson;

1.1.2 表(table)

 

比如数据库像是一个抽屉,表就类似于一个个不同标签的文件夹,而文件夹里可以存储数据,表是某种特定类型结构化清单

而一张表,应该存储一类数据,比如订单信息、账号信息、商品信息就应该分开三个表记录。

数据库中,每张表的名字是唯一的,在同一个数据库中不能出现重名,但不同数据库却可以。

1.1.3 列和数据类型(column)

 

表由列组成,所有的表都是由列组成,列是竖着显示的,如姓名、分数、科目这样的形式。

%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:/mysql/bin;C:\Users\Administrator\AppData\Local\Programs\Python\Python39\Scripts;C:\Users\Administrator\AppData\Local\Programs\Python\Python39

1.1.4 行(row)

例如,列记录了每个客人的各种属性,而行就是展示单独一个客人的全部属性。

1.1.5 主键(primary key)

 

表中,每一行都应该有一个可以唯一标识自己的一列(或一组列),一个顾客可以通过编号查找,订单表可以通过订单编号查找,以此类推。

  • 任意两行都不可以存在相同的主键
  • 每个行都必须有一个主键值主键不允许出现NULL值)通常使用id代表主键

主键的好习惯

  • 不更新主键的值
  • 不重用主键列的值
  • 不在主键列使用可能更改的值(比如不能用姓名来做主键,姓名有更改的风险)

1.2 什么是SQL(Structured Query Language)

 

SQL是结构化查询语言的缩写,专门用来和数据库通信的语言。

SQL有以下优点

  • SQL不是某个特定数据库的专用语言,几乎所有DBMS都支持SQL。
  • SQL语法比较简单,语句都是由英语单词组成。
  • SQL搭配其语言元素,可以处理非常复杂和高级的数据库操作。

另一个好习惯,大写显示MySQL关键词,小写显示列、名、判断语句等

第三章 使用MySQL

3.1 连接

 

为了连接MySQL,需要以下信息:

  • 主机名(计算机名)——如果连接到本地MySQL,为localhost
  • 端口(如果不是默认3306,需手动填写)
  • 一个合法的用户名
  • 用户口令(默认账号是root,密码也是root,拥有全部权限)

3.2 选择数据库

 

在刚打开MySQL数据库时,没有任何数据库打开供人使用,需选择一个数据库,使用USE关键字。

例如,有一个数据库liang,使用时,输入USE liang(表名)

3.3 了解数据库和表

 

数据库、表、列、用户、权限等信息被存储在数据库和表中,使用SHOW命令来显示这些信息,如SHOW DATABASES;

而显示这个数据库下,有哪些表,使用SHOW TABLES;

还可以显示表中的列名,SHOW columns FROM student(表名);

第四章 检索数据

4.1 SELECT语句

 

最简单的就是查询语句,比如student表。

公式:SELECT 列 FROM 表——可单独输入一个/多个列名,或是输入通配符*表示搜索全部的列

参考:SELECT name,id FROM student

4.5 检索不同的行

 

公式:SELECT DISTINCT 列 FROM 表

SELECT DISTINCT name FROM student

如果筛选出来的结果(行)有相同的,需要distinct关键字来区分重复项(但只能筛选出一部分值)

4.6 限制结果(limit)

 

公式:SELECT 列 FROM 表 LIMIT 数字

SELECT*FROM student LIMIT 3

SELECT*FROM student LIMIT 5,5

 

可以控制返回值有几行,比如只想看到前几行数据,默认是写的行数,两个值如5,5 —表示从第5行往下再数5行。

4.7 使用完全限定的表名

 

有一些情形需要完全限定表名,这样会让语句可读性更高,比如:

SELECT student.name FROM student

第五章 排序检索数据

5.1 排序数据(order by)

 

公式:SELECT 列 FROM 表 order by 列 asc(desc)——默认升序排列asc

SELECT*FROM student ORDER BY score DESC(根据学生分数,降序排列)

SELECT*FROM student ORDER BY score ASC LIMIT 1(找出分数最低的那个人)

多个条件排序,只不过order by后面可以多个列,比如先根据价格,再根据姓名做排序。

第六章 过滤数据

6.1 使用WHERE语句

where条件判定:

SELECT*FROM student WHERE score>=90

SELECT*FROM student WHERE name="张三"

操作符between

SELECT*FROM student WHERE score between 80 AND 90

操作符OR和IN

SELECT*FROM student WHERE score>90 OR score<60

——OR操作符,匹配两个条件中的任意一个

SELECT*FROM student WHERE score IN(80,90) ORDER BY id

——IN操作符,范围内每个条件都可以匹配,IN 和OR完成的筛选 结果一样,但是使用IN有的时候更清晰。

空值检查(NULL)

SELECT prod_name FROM products WHERE prod_price IS NULL;

第七章 数据过滤

7.1 组合WHERE字句

 

上一章的子句只是单个字段查询,下面进行组合查询,使用OR、AND等方式。

7.1.1 AND操作符

 

SELECT*FROM products WHERE prod_id="TNT3" AND vend_id=3;

只有同时符合,才可以查询出来;每添加一个新的筛选条件,就多加一个AND

7.1.2 OR操作符

 

SELECT*FROM products WHERE prod_id="TNT3" OR vend_id=4;

只要其中一个筛选项满足,就可以显示查询结果

7.1.3 计算次序

 

WHERE可包含任意数目的AND和OR操作符,允许两者结合以进行复杂和高级的过滤。

SELECT*FROM products WHERE (prod_id="TNT3" OR vend_id=4) AND prod_price>5;

使用圆括号进行分隔,优先执行括号内的语句,后执行括号外的;否则优先执行AND,其次OR

7.2 IN操作符

 

SELECT vend_id,prod_name FROM products WHERE vend_id IN(1,2,3,4)

IN里的合法值,由逗号分隔,IN的好处,可以包含其他SELECT语句,速度比OR快,且更加直观

7.3 NOT操作符

 

否定它之后的所有条件关键字,在与IN同时使用时,效果很好

第八章 用通配符进行过滤

8.1 LIKE操作符和通配符

下划线:_表示任意字符的一次匹配

下划线_通配符(匹配单个字符):

SELECT*FROM student WHERE name LIKE "张_" ——第一个字匹配张,第二个字任意

 

百分号:%表示任意字符的任意次数,但不能匹配NULL

百分比%通配符(匹配全部字符):

SELECT*FROM student WHERE name LIKE "%%" ——筛选出所有内容

SELECT*FROM student WHERE name LIKE "%辽" ——前面匹配任意字符,最后一个字匹配辽

SELECT*FROM student WHERE name LIKE "张%" ——第一个字匹配张,后面匹配任意字符

第九章 正则表达式进行搜索(P62)

9.1 正则表达式介绍

正则表达式是匹配一段字符串中特殊的内容,比如一段文字中提取电话号码,找到重复的单词,替换URL为HTML链接等等

SELECT*FROM zhengze WHERE description REGEXP '7983'

——REGEXP,包含的意思

LIKE和REGEXP的区别,LIKE是匹配整个列,但REGEXP匹配的是列值,后面会用^等关键字。另外LIKE是要全部匹配,REGEXP匹配一部分即可。

SELECT*FROM zhengze WHERE description REGEXP '群众|作家|党员'

——类似关键字OR

SELECT*FROM zhengze WHERE description REGEXP '[群众作家党员]'

——中括号内进行匹配

SELECT*FROM zhengze WHERE description REGEXP '[0-9a-z]'

——匹配包含数字英文的内容

SELECT*FROM zhengze WHERE description REGEXP ' \\.'

——双斜杠为前置,匹配特殊字符,如果要匹配反斜杠\,那就需要写三个\\\

匹配一个手机号码

1[0-9]{10} ——首数字1,中间任意数字,除了1外有10位长度,加起来11位

匹配QQ号码:

[1-9]{4,10} ——首数字不为0,总长度5-11(很奇怪,匹配到的值超过这个数目)

匹配A类IP地址

[1-9].[0-9].[0-9].[0-9] ——首数字不为0,每个之间句号分隔,总共4个字节

匹配多个实例

定位元字符

SELECT*FROM zhengze WHERE description REGEXP '^[是].*[员]'

——^文本的开始,.*匹配是和员两个字中间的任意多个字符,原句子:是一位演员

10章 创建计算字段(P73)

10.1 计算字段

  • 如果想在一个字段既显示公司名、也显示地址,但这两个通常在不同的列
  • 城市、洲和邮政编码存储在不同的列,但邮件需要把它们组合起来检索
  • 列数据是大小写混合的,但报表程序需要把所有数据都按照大写显示
  • 物品订单表存储价格和数量,打印发票时,需计算物品的总价格/平均价格或其他计算

10.2 拼接字段

将两个列拼接起来,可使用Concat(str1,str2)函数来拼接

SELECT CONCAT(name,country) FROM vendors ——直接拼接即可

SELECT CONCAT(name,' ',course) FROM student ——可以用字符做分隔,比如这里用了空格分隔开两个合并的字符

10.3 执行算数计算

SELECT prod_id,quantity,item_price,quantity*item_price AS price_all FROM orders

——筛选出的结果,price_all这个字段显示4个字段,第4个就是乘积

11章 使用数据处理函数(P80)

11.1 函数

  • 用于处理文本串(如删除或填充值,转换值为大写或小写)。
  • 用于在数值数据上进行算术操作(如返回绝对值,进行代数运算的数值函数)。
  • 用户处理日期和时间值,并从这些值中提取特定成分(如两个日期之差,检查日期有效性等)的日期和时间函数。
  • 返回DBMS正使用的特殊信息(如返回用户登录信息,检查版本细节)的系统函数。

11.2.1 文本处理函数

 

UPPER(str)——将小写字母变为大写字母

LOWER(str)——转为小写

LENGTH(str)——返回串的长度

LOCATE(substr,str)——返回子串的位置,substr是子串,str是母串

RTRIM(str)——去掉字符串右边的空格

LTRIM(str)——去掉字符串左边的空格

11.2.2 日期处理函数

 

ADDDATE(expr,day)

——增加一个日期(),如select AddDate('2020-04-08',3)

ADDTIME(expr1,expr2)

——expr1是时间表达式,也可以像上面那样,但加的是秒,不会自己换算

CURDATE()

——返回当前日期

CURTIME()

——返回当前时间

DATE(expr)

——返回日期(不显示具体时间)

DATEDIFF(expr1,expr2)

——返回两个日期之差,如select DATEDIFF('2020-04-08','2020-04-09')

DATE_ADD((date,INTERVAL expr unit))

——日期运算函数,如select DATE_ADD('2020-04-04 01:00:03',INTERVAL 3 HOUR)

DATE_FORMAT(date,format)

——返回一格式化的日期或时间串,如select DATE_FORMAT('2020-04-04 01:00:03','%W %M %Y') %W返回星期几如Monday,%M返回月份如April,%Y返回年如2020

Day(date)

——返回一个日期的天数,如select DAY('2020-04-30'),返回30(天),同理Hour、Month、Minute、Now、Second、Time、Year是同样的原理

11.2.3 数值处理函数

 

主要用于代数、三角或几何运算,因此使用不频繁

ABS(x)——返回绝对值,如select Abs(-30)

COS(x)——返回角度余弦,如select Cos(1),同理Sin和Tan

EXP(x)——返回指数值

MOD(x,y)——返回除操作的余数

PI()——返回3.141593

RAND()——返回1以下的随机小数,与order by共同使用

SQRT(x)——返回平方根

12章 汇总数据(P86)

12.1 聚集函数

 

  • 确定表中行数,或满足某个条件的行数
  • 获得表中行组的和
  • 找出表列(或所有行或某些特定的行)最大值、最小值和平均值

AVG()——返回某列平均值,如select AVG(quantity) from orders

COUNT()——返回某列的行数 ,count(*)则是对所有行计数

MAX()——返回某列的最大值

SUM()——返回某列值总和

DISTINCT()——只包含不同的值,select avg(DISTINCT item_price) from orders

12.3 组合聚集函数

 

实际应用中,更适合叠在一起使用

select

count(*) as shuliang,

min(quantity) as min_quantity,

max(quantity) as max_quantity,

avg(item_price) as avg_price

from orders

13章 分组数据(P94)

13.1 数据分组

 

如果想知道每个供应商提供的产品总数、或者只显示单个供应商提供的产品之类的问题,就需要分组查询

13.2 创建分组

 

group by指示MySQL分组数据,这里显示的是,统计分组后,每个prop_id对应的数量,很明显这里FB出现了两次

select prod_id,count(*) as number_prod from orders 

GROUP BY prod_id

显示结果如图

13.3 过滤分组

 

Having子句,类似Where,也可替代Where

Having过滤分组,Where过滤行

例如:想要列出至少有两个订单的所有顾客,为得到这种数据,必须基于完整的分组而不是个别的行进行过滤。

 

-- having这里如果用where就报错了,因为group by之后已经转成分组,而where不能搜索分组

select name,course,score

from student

group by course

having score>1

order by score asc

具体操作:先用group by做第一次分组排序,再用order by做第二次分行排序

Group by和Order by的区别

 

比如说,我要做一个排序,显示分数/单价的排序,用order by合适;

如果要排序每个科目的学生姓名,group by合适。

14章 使用子查询(P101)

嵌套在查询语句里面的查询语句,就是子查询

  1. 检索包含物品TNT2的所有订单的编号
  2. 检索具有前一步骤列出的订单编号的所有客户的ID
  3. 检索前一步骤返回的所有客户ID的客户信息

orderitems表

1步,找到订单编号

select order_num from orderitems where prod_id="TNT2"

orders表

2步,通过第1步的order_num,找到对应的cust_id

select cust_id

from orders

where order_num in(select order_num from orderitems where prod_id="TNT2")

customers表

3步,通过第2步的cust_id,找到对应的全部信息

select*from customers

where cust_id=(select cust_id

from orders

where order_num in(select order_num

from orderitems

where prod_id="TNT2"))

14.3 作为计算字段使用子查询

 

使用子查询的另一个方法是创建字段,假如需要显示customers表中,每个客户的订单总数,订单和客户ID存储在orders表中。

  1. customers表中检索客户列表。
  2. 对于检索出的每个客户,统计其在orders表中的订单数目。

第一步

select cust_name,cust_address

from customers

第二步

select cust_name,cust_address,(select count(*)

from orders

where orders.cust_id=customers.cust_id)

from customers

--嵌套时,select查询的参数,带上表的名字来强化

15章 联结表(108)

15.1 联结

 

主键:要求主键列数据唯一,并且不允许为空。

外键:用于在两个表之间建立联系,需要指定引用主表的那一列

比如说,用户id属性,在表1和表2都有,它可以是表1的主键,那么就可以说它也是表2的外键

 

联结:只存在于Select查询当中,并不是真实的表,用于通过一个相同的列的值,查询两个不同表的数据,From使用两个表,而且相同id这一个数据,需要指定从哪一个表取这个数据。

Where字句很重要,两个表的联结是用笛卡尔积的方式,如果不用,会产出很多错误数据。

Select vendors.vend_id,vend_name,prod_name,prod_price

From vendors,products

Where products.vend_id=vendors.vend_id

语法略微有不同,下面是内部联结语句,Inner Join的用法,上面的叫做等值连接,二者是一样。

Select vendors.vend_id,vend_name,prod_name,prod_price

From vendors inner join products

On vendors.vend_id=products.vend_id

对照第14章的子查询,两种方法都可以得出想要的结果,

select*from customers

where cust_id=(select cust_id

from orders

where order_num in(select order_num

from orderitems

where prod_id="TNT2"))

另一种方法:

select cust_name,cust_cust_contact

from orderitems,orders,customers

where orderitems.order_num=orders.order_num

and orders.cust_id=customers.cust_id

and prod_id='TNT2'

16章 创建高级联结(P117)

16.1 使用表别名

 

就是给表起个简单的名字,比如orders起名叫o,products起名叫p,把长的名字转化成短的名字,方便书写,缩短SQL语句

Select o_I.prod_id,cust_name,quantity

From orderitems as o_i,orders as o,customers as c

Where o_i.order_num=o.order_num

and o.cust_id=c.cust_id and prod_id='TNT2'

16.2.1 自联结

 

比如products表里面,有一个物品DTNTR是损坏的,我需要知道在同一张表里,生产者个DTNTR的供应商,又生产了其他什么物品,那就是同一张表,做了两次查询

子查询

select prod_id,vend_id,prod_name

from products

where vend_id=(select vend_id

from products

where prod_id="DTNTR")

联结

select p1.prod_id,p1.prod_name

from products as p1,products as p2

where p1.vend_id=p2.vend_id

and p2.prod_id='DTNTR'

相比起来,联结可能更简洁一些,二者都比较容易理解

16.2.2 自然联结(目前没看懂)

 

16.2.3 外部联结

 

内部联结是将两个表里,都含有的字段做关联,但如果想要知道没有关联的行,就要用外部联结。

  1. 对每个客户下了多少订单进行计数,包括那些至今还没有下单的客户
  2. 列出所有产品以及订购数量,包括没人订购的产品
  3. 计算平均销售规模,包括那些至今未下订单的客户

先用一个内部联结的例子,检索orderscustomers表,用户id及订单的关系

select o.cust_id,o.order_num,c.cust_name

from orders as o INNER JOIN customers as c

on o.cust_id=c.cust_id

输出是

select o.cust_id,o.order_num,c.cust_name

from customers as c LEFT JOIN orders as o

on o.cust_id=c.cust_id

输出是

16.3 使用带聚集函数的联结

 

查询每个客户对应的订单总数

select o.cust_id,c.cust_name,count(o.order_num) as num_order

from customers as c INNER JOIN orders as o

on o.cust_id=c.cust_id

group by c.cust_id

注意事项

  • 联结类型,一般使用内部联结,但外部联结也是可用的
  • 保证正确的联结条件,否则将返回不正确的数据
  • 提供联结条件,否则会得出笛卡尔积

实战演习:

问题1:得出每一门学科对应的最高分数

select course,max(grade)

from student

group by course

问题2:接上一步,得出每门科目最高分数的人是谁

select b.course,b.Max_grade,a.name

from (select course,max(grade) as Max_grade from student group by course)as b,student as a

where b.Max_grade=a.grade and b.course=a.course

问题3:SQL写出每一位同学的总成绩

select distinct name,sum(grade) as all_grade

from student

group by name

第二步:其中张三,李四植树总分各加了100分,这里的排列就是先把张三、李四不加入排列,再加入排列(再次加入时,已经给加分了)

select name,SUM(grade)

from student

where name not in('李四','张三')

GROUP BY name

Union

select name,SUM(grade)+100

from student

where name in('李四','张三')

GROUP BY name

17章 组合查询(P124)

多数SQL查询只包含一个或多个表中返回数据的单条SELECT语句,MySQL允许执行多个查询(多个SELECT语句),并将结果作为单个查询结果集返回。这些组合查询成为并(union)或复合查询。

使用条件

  • 在单个查询中从不同表返回类似结构的数据,
  • 对单个表执行多个查询,按单个查询返回数据。
  • 自己记录一条,两个select筛选的列名应该一致,不然多出的字段会排成行而不是列
  • 只允许一个order by/group by

18章 全文本搜索(P130)

18.1 理解全文本搜索

 

8章、第9章分别使用了通配符(Like)和regexp(正则表达式)来匹配,但存在限制。

  • 性能——通配符和正则匹配通常要尝试访问所有行,非常耗时。
  • 明确控制——使用通配符和正则匹配很难。
  • 智能化的结果——例如,一个特殊词的搜索将会返回包含该词的所有行,而不区分包含单个还是包含多个匹配的行。选择更好的排序方式来展示它们。

18.2 使用全文本搜索

 

为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有的索引和重新索引。

在索引之后,SELECT可与Match()和Against()一起使用以实际进行搜索。

18.2.1 启用全文本搜索支持

 

创建表时启用全文本搜索,CREATE TABLE里,加一行FULLTEXT(note_text),这里的索引是这一列,也可以选择多个列。

在定义之后,MySQL自动维护该索引,在增加、更新或删除时,索引随之自动更新。也可以创建表之后,定义索引。

18.2.2 进行全文本搜索

 

在索引之后,使用Match()和Against(),Match()指定被搜索的列,Against()指定要使用的搜索表达式。可实际使用后,发现并查不到数据,实际做下去,发现不如Like容易

select name from student

where Match(name) Against("梁")

19章 插入数据(P142)

19.1 数据插入

 

INSERT是用来插入(或添加)行到数据库表的,插入可以用几种方式使用:

  1. 插入完整的行
  2. 插入行的一部分
  3. 插入多行
  4. 插入某些查询的结果

19.2 第一种:插入完整的行

 

Insert Into 表名

Values(10,'梁君','家庭住址是XXXOOO',NULL)

Values中每个值对应数据库结构而定,每个列必须有值,没有值的使用NULL,第一个主键可以使用NULL,前提是这个主键支持自动增量,这样可以不必输入最前面的一列值。

Insert Into student(id,name,course,grade)

Values(NULL,'梁大','物理',30)

如果把表中具体的参数标出来,那样更具体,并且在表结构变动时,不会出错。

提升整体性能,可在Insert和Values之间加入Low_Priority,指示MySQL降低Insert语句的优先级。这个Low_Priority也支持后面的Update和Delete。

19.3 第二种:插入多行

 

简单一点的方式,就在Values后面加个逗号,再加一些数据即可。

19.4 第四种:插入检索出的数据

 

该场景参考

Insert Into student(id,name,course,grade)

Select id,name,course,grade from student

报错了,原因主键id的值不能相同,如果不能保证两张表的数据,可以不写主键(也就是id列)

20章 更新和删除数据(P150)

20.1 更新数据

 

更新(修改)表中的数据,可使用Update语句,可采用两种方式使用:

  • 更新表中特定行
  • 更新表中所有行

Update语句非常容易使用,由3部分组成,分别是:

  1. 要更新的表
  2. 列名和它们的新值
  3. 确定要更新行的过滤条件

Update student

Set name='梁君改',grade=99

Where id=1

如果不使用Where作为筛选和限制,则会更改所有列的值,支持多行修改

20.2 删除数据

 

从一个表中删除(去掉)数据,使用DELETE语句,可以用两种方式使用DELETE:

  1. 从表中删除特定的行
  2. 从表中删除所有行

20.3 更新和删除的指导原则

 

需要遵守的规则:

  1. 尽量不用Update或Delete语句,如果使用,需要加入Where筛选条件
  2. 保证每个表都有主键(主键是用来保证数据完整性)
  3. 在使用Update或Delete语句之前,使用Select查询,防止更新/删除错误
  4. 使用强制实施引用完整性的数据库

Delete from 表 Where name="梁君"

21章 创建和操纵表(P155)

21.1 创建表

 

使用交互式创建和管理表的工具(MySQL或是其他的数据库软件)、MySQL语句操纵

21.1.1 表创建基础

 

为利用Create Table创建表,必须给出下列信息

  1. 新表的名字,在关键字Create Table之后
  2. 表列的名字和定义,逗号分隔

Create table

(

id int not null Auto_Increment,

name char(50) not null,

course char(50) not null,

score int not null,

address char(255) null,

primary key(id)

)Engine=InnoDB;

上面的Auto_Increment是自动增量, primary key是主键,Engine=InnoDB是数据库引擎。

注意事项:

  1. MySQL语句忽略空格,可以在一行中输入,也可以分行输入,互不影响
  2. 处理现有的表,创建表格不是覆盖,需删除旧表,再创建新表

21.1.2 使用NULL值

 

在创建表时,需规定哪一列允许NULL值还是不允许NULL值,主键通常都需要值。

NULL值和空串不一样,空串是'',实际上是有值,而NULL就是无值。

21.1.3 主键再介绍

 

主键值必须唯一,每个行必须要有唯一的主键值。如果主键使用单个列,那它的值必须唯一。如果使用多个列,这些列的组合值必须唯一。

21.1.4 Auto_Increment

 

自动增量,每个表只允许一个Auto_Increment列,而且它必须被索引(比如,使它成为主键)

21.1.5 指定默认值

 

Create table student4

(

id int not null Auto_Increment,

name char(50) not null,

course char(50) not null DEFAULT '语文',

score decimal(8,2) not null,

Primary Key(id)

)Engine=InnoDB;

这里的decimal(8,2)指的是类型、长度、小数,其实和上面的char(50)意思是一样的

DEFAULT的值,就是默认值

21.1.6 引擎类型

 

前面几个创建表,使用的都是Engine=InnoDB引擎,如果不写,可能默认使用MyISAM引擎,但不是所有语句都能使用它。所以,人为规定了InnoDB引擎。

  • InnoDB不支持全文搜索。
  • Memory在功能等同于MyISAM,但由于数据存储在内存(不是硬盘)中,速度很快(适合临时表)。
  • MyISAM是一个性能极高的引擎,它支持全文本搜索,但不支持事务管理。
  • 混用引擎,不能作用于外键,使用一个引擎的表不能引用使用不同引擎的表的外键。

21.2 更新表

 

更新表定义,可使用ALTER TABLE语句,必须给出以下信息:

  1. ALTER TABLE之后给出要更改的表名(该表必须存在,否则出错)
  2. 所做更改的列表

Alter Table vendors

Add vend_phone char(20);

这条语句给vendors表增加一个名为vend_phone的列,必须明确其数据类型。

Alter Table vendors

Drop Column vend_phone ——Drop Column删除列

Alter Table另一个用途是定义外键,下面是外键的代码

Alter Table orderitems

Add CONSTRAINT fk_orderitems_orders

FOREIGN Key(order_num) REFERENCES orders(orders_num);

21.3 删除表(P164)

 

删除一整张表

Drop Table 表名

21.4 重命名表

 

Rename Table 旧表名 to 新表名 ——可以更改多个表名,一排一排的修改即可

22章 使用视图(P166)

22.1 视图

视图是虚拟的表,视图也是一个查询语句,提供的不是数据而是根据检索数据的查询。视图提供了一种MySQL的Select语句层次的封装,可以用来简化数据处理以及重新格式化基础数据或保护基础数据。

视图一般用于检索Select,而不用更新Insert、Update、Delete。

视图的特点:

  1. 重用SQL语句。
  2. 简化复杂的SQL操作,在编写查询后,可以重用而不需要知道细节。
  3. 使用表的部分而不是全部。
  4. 保护数据,可以让用户查看一部分数据而不是全部。
  5. 更改数据格式和表示,视图可返回与底层表的表示和格式不同的数据。

22.1.2 视图的规则和限制

 

  1. 与表一样,视图必须唯一命名(视图和表的名字不能相同)。
  2. 对于可创建的视图数量无规定。
  3. 为了创建视图,必须有足够权限。
  4. 视图可以嵌套,可以从其他视图的检索数据,来构造视图。
  5. ORDER BY可以用在视图,但如果检索数据中也有ORDER BY,则会被覆盖。
  6. 视图不能索引,也不能有关联触发器或默认值。
  7. 视图可以和表一起使用,例如,编写一条联结表和视图的SELECT语句。

22.2 使用视图

 

  1. 视图用Create View语句创建
  2. 使用Show create new 视图名;来查看创建视图的语句
  3. Drop删除视图,语法为Drop view 视图名
  4. 更新视图时,先用Drop再同Create,也可以Create or replace view,如果要更新的视图不存在,会创建一个;如果已存在,会更新视图

22.2.1 利用视图简化复杂的联结

 

创建视图,后面是一整块查询语句,前面这一行就是创建一个视图

Create View 视图名 as

Select s.id,s.name,s.course,s.grade,info.address,info.beizhu

From info,student as s

Where info.name=s.name

22.2.2 用视图重新格式化检索出的数据

22.2.3 用视图过滤不想要的数据(也就是在检索中不检索部分数据)

22.2.4 使用视图与计算字段

22.5 更新视图

 

视图是可更新的,可以用Insert、Update和Delete,视图本身没有数据,实际上是对基表增加或删除行。但是,并非所有视图都可更新,如果MySQL不能确定被更新的基数据,则不允许更新。

  1. 分组(使用Group By和Having)
  2. 联结Union
  3. 子查询
  4. 聚集函数(Min()、Count()、Sum()等)
  5. Distinct
  6. 导出(计算)列

23章 存储过程(P174)

23.1 存储过程

 

如果有多种情况:

  1. 为了处理订单,需要核对保证库存中有相应的物品。
  2. 如果库存有物品,这些物品需要预定,不卖给别人。
  3. 库存中没有的物品需要订购,需要与供应商沟通。
  4. 关于哪些物品入库(并且可以立即发货)和哪些物品退订,需要通知相应客户。

 

存储过程,简单的说,就是为以后的使用而保存的一条或多条MySQL语句的集合,可将其看成批处理,它们的作用不止是批处理。而保存后的SQL语句,后续可持续使用。

23.2 为什么使用存储过程

 

一些主要理由:

  1. 通过把处理封装在容易使用的单元中,简化复杂操作
  2. 由于不要求反复建立一系列处理步骤,这保证了数据的完整性,如果所有人都使用这个存储过程,则使用的代码都是相同的。这一点的延伸就是防止错误,需要执行的步骤越多,越容易出现错误。
  3. 简化对变动的管理。如果表名、列名或业务逻辑有变化,只需要更改存储过程的代码。动用它的人员甚至可以不知道这些变化。

 

换句话说,使用存储过程有3个主要好处,简单、安全、高性能。

难点1:存储过程编写复杂 2.权限相关,有可能没有对应权限。

23.3 使用存储过程

23.3.1 执行存储过程

 

MySQL称存储过程的执行为调用,使用Call,Call接受存储过程的名字以及需要传递给它的任意参数。

Call productprice(@pricelow,

@pricehigh,

@priceaverage)

其中,执行名为procutproce的存储过程,它计算并返回产品最低、最高和平均价格。

存储过程可以显示结果,也可以不显示。

存储过程实际上也是一种函数。

23.3.2 创建存储过程

 

Create Procedure aaa()

Begin

select course,max(grade)as MAX_grade

from student

group by course;

End;

Begin和End语句用来限定存储过程体,过程体本身仅是一个简单的Select语句。

23.3.3 删除存储过程

 

Drop Procedure aaa;

这里就不用写函数,而直接写过程体名字就行。

23.3.4 使用参数

 

存储过程,只简单的显示Select语句的结果。一般情况,存储过程并不显示结果,而且把结果 放到指定的变量(内存中一个特定的位置,用来临时存储数据)。

第一步:创建带参数的存储过程

Create Procedure abc(

Out avg decimal(8,2),

Out max decimal(8,2)

)

BEGIN

Select avg(grade) Into avg from student;

Select max(grade) Into max from student;

END;

第二步:调用存储过程(存储过程是一个函数,形参必须都传递进去)

Call abc(@avg,@max)

第三步:查询变量值(可以查询一个,可以查询多个)

Select @avg,@max

 

MySQL支持IN(传递给存储过程)、OUT(从存储过程中传出,还有一种INOUT(书中未提及)。

复杂的存储过程

-- 新建

Create Procedure tax(

In onumber INT,

In taxable Boolean,

Out final_total decimal(8,2))

Begin

-- 定义总钱数和税率

Declare total decimal(8,2);

Declare taxrate INT DEFAULT 6;

-- 先计算一个总钱数,这句话就是说,输入的订单号等于表中已有的订单号

select sum(item_price*quantity) from orderitems where order_num=onumber

Into total;

-- 判断是否需要税率

If taxable Then

Select total+(total/100*taxrate)

Into total;

End if;

-- 最后,保存计算后数据

select total into final_total;

End

调用时,使用

Call tax(20005,0,@total);

Select @total;

第二个参数,输入0,不走税率;输入1,走税率计算。而第三个就是计算结果。

23.3.6 检查存储过程

 

显示用来创建一个存储过程的Create语句,可以用下面显示。

Show Create Procedure tax;

获得何时、由谁创建等详细的存储过程列表,使用下面语句。

Show Procedure Status;

24章 使用游标(P185)

24.1 游标

 

有时,需要在检索出来的行中前进或后退一行或多行,这就是使用游标的原因。

游标是一个存储在MySQL服务器上的数据库查询,不是一条Select语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。

24.2 使用游标

 

  1. 使用前,必须声明(定义),这个过程没有检索数据,只是定义要使用的Select语句。
  2. 一旦声明后,必须打开游标以供使用,这个过程用前面定义的Select语句把数据实际检索出来。
  3. 对于填有数据的游标,根据需要取出(检索)各行。
  4. 在结束游标使用时,必须关闭游标。

24.2.1 创建游标

 

Declare创建游标,Declare命名游标,并定义相应的Select语句,根据需要带Where和其他子句。

Create Procedure processorders()

Begin

Declare ordernumbers cursor

For

Select order_num From orders;

End;

这个存储过程并没有做很多事情,Declare语句用来定义和命名游标,这里的游标名字就是ordernumbers。存储过程处理完成后,游标会消失。

定义游标之后,可以打开它。

24.2.2 打开和关闭游标

 

游标使用Open cursor语句来打开,比如Open ordernumbers

处理完成后,使用Close ordernumbers进行关闭,End语句也会自动关闭游标。

后面的以后补充吧,实在看不下去了 ——2020年4月15日

25章 使用触发器(P192)

25.1 触发器

 

比如当执行了某条/某些语句,在事件发生时自动执行,应该怎么做:

  1. 每当增加一个顾客到某个数据库表时,都检查电话格式是否正确,州的缩写是否大写。
  2. 每当订购一个产品,都从库存数量中减去订购的数量。
  3. 无论何时删除一行,都在某个存档表中保留一个副本。

所有这些例子,都是它们需要在某个表发生更改时自动处理,这就是触发器

触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句,或位于Begin和End之间的一组语句。

  • DELETE
  • INSERT
  • UPDATE

其他MySQL语句不支持触发器。

25.2 创建触发器

 

在创建触发器时,需要给出4条信息:

  1. 唯一的触发器名;
  2. 触发器关联的表;
  3. 触发器应该响应的活动(Delete、Insert和Update)
  4. 触发器何时执行(处理之前或之后)

Create Trigger newproduct After Insert to products

For Each Row Select "一二三四";

Create Trigger:创建名为newproduct的触发器

After Insert to:在Insert语句成功执行后执行

For Each Row:代码对每个插入行执行

文本"一二三四":对每个插入的行显示一次

25.3 删除触发器

 

Drop Trigger newproduct;

25.4 使用触发器

25.4.1 Insert触发器

 

Insert触发器再Insert语句执行之前或之后执行。

  1. Insert触发器代码内,可引用一个名为New的虚拟表,访问被插入的行
  2. Before Insert触发器中,New中的值也可以被更新(允许修改被插入的值)
  3. 对于Auto_Increment列,New在Insert执行之前包含0,在Insert执行之后包含新的自动生成值。

一个更好的,在插入数据后赋予新id的方法:

Create Trigger neworder After Insert On orders

For Each Row Select NEW.order_num;

创建了一个名为neworder的触发器,它在After Insert On orders执行,orders是数据库表,在插入一条新数据后,触发器从NEW.order_num得到这个值并返回。

Insert Into orders(order_date,cust_id)

Values(Now(),10001)

这里输入语句,只输入了两个字段,返回值会自动更新前面的order_num字段。

再补充一个完整的插入步骤

1.在设计表界面,可以看到这个表有没有触发器

2.在orders表,插入一条新数据之后,再插入一条虚拟表格new的新数据到archive_orders表,而为什么用new而不是old,思考一下,如果是删除,就用old。

注意,这里的after,尝试过改成before,返回的插入结果,id是0,所以还是用after

Create Trigger neworders222 after insert on orders for each row

begin

Insert Into archive_orders(order_num,order_date,cust_id)

Values(new.order_num,new.order_date,new.cust_id);

end

3.删除触发器

drop trigger neworders222

25.4.2 Delete触发器

 

Delete触发器在Delete语句执行之前/之后执行。

  1. Delete触发器代码内,可以引用一个叫做Old的虚拟表,访问被删除的行
  2. Old中的值全都是只读的,不能更新

Create Trigger deleteorder Before Delete On orders For Each Row

Begin

Insert Into archive_orders(order_num,order_date,cust_id)

Values(Old.order_num,Old.order_date,Old.cust_id);

End

使用Before Delete触发器的优点,先存档,再删除,更加稳妥。

arcive_orders这个表用来存储被删除的内容,而被删除的内容,暂时是存储在Old表中,就相当于把Old里的缓存放到真正的表中。

25.4.3 Update触发器(P196)

 

  1. Update触发器代码中,可以引用Old的虚拟表访问以前(Update语句前)的值,引用一个名为New的虚拟表访问新更新的值。
  2. Before Update触发器中,New中的值可能也被更新(允许更改将要用于Update语句中的值)。
  3. Old中的值全部是只读,不能更新。

 

Create Trigger updatevendor before update on vendors

for each row set New.列名=Upper(New.列名);

New.列名=Upper(New.列名)

25.4.4 关于触发器的进一步介绍

 

  1. 创建触发器可能需要特殊的安全访问权限,但是,触发器是自动的。如果Insert、Update、Delete语句能够运行,则相关触发器也能执行。
  2. 触发器一种很有意义的使用是创建审计跟踪。
  3. 触发器不支持Call语句,存储过程代码需要复制到触发器内。

26章 管理事务处理(P199)

26.1 事务处理

 

并非所有引擎都支持事务处理,比如默认的MyISAM不支持明确的事务处理管理,而InnoDB支持,所以全篇都在用InnoDB引擎。

事务处理可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行。

假如多个表之间有关联,有同一个字段的关联如订单编号,当出现某种数据库故障(如超出磁盘空间、安全限制、表锁等)阻止了这个过程,数据库可能就会出现空白订单编号的情况。

这就是为什么使用事务处理

  • 事务(transcation)指一组SQL语句
  • 回退(rollback)指撤销指定SQL语句的过程
  • 提交(commit)指将为存储的SQL语句结果写入数据库表
  • 保留点(savepoint)指事务处理中设置的临时占位符,可以对它发布回退

26.2 控制事务处理

 

管理事务处理的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。

Start Transcation ——标识事务的开始

26.2.1 使用Rollback

 

MySQL的Rollback命令用来回退(撤销)MySQL语句,执行下来,这个表删除又回来了。rollback只能在一个事务处理内使用,在执行Start Transaction命令之后生效。

Select*from info

Start Transaction

-- 删除掉这个表

Delete from info

-- 回滚

Rollback

Select*from info

26.2.2 使用Commit

 

一般的MySQL语句是直接针对数据库表执行和编写的,称为隐含提交,即提交(写/保存)是自动进行的。但是在事务处理块总,提交不会隐含进行,需要使用Commit语句。

执行几次后的结果,两个Delete命令,保证系统中两个表完全删除掉这条记录。也就是说,start transaction之后,第一次执行delete命令后,是不会真正删除的,如果再输入一个commit或重新执行一次delete语句,才会执行。

Start Transaction;

Delete From orders where order_num=10002;

Delete From orderitems where order_num=10002;

Commit;

26.2.3 使用保留点

 

简单的Rollback和commit语句就可以写入或撤销整个事务处理。但是更复杂的事务处理需要部分提交或回退。

保留点,使用Savepoint语句,每个保留点有唯一名字,可创建多个保留点。

Savepoint delete1;

而回退到保留点的语句,就是

Rollback to delete1;

如何释放保留点?

  1. 执行一条Rollback或Commit后自动释放
  2. Releasesavepoint也可以释放

26.2.4 更改默认的提交行为

 

默认MySQL行为是自动提交所有更改,而且立即生效。

Set autocommit=0;

——标志决定是否自动提交更改,0(假)指示MySQL不自动提交更改,直到autocommit设置为真为止。

27章 全球化和本地化(P204)

27.1 字符集和校对顺序

 

数据库表用来存储和检索数据。不同的语言和字符集需要以不同的方式存储和检索。因此MySQL需要适应不同的字符集(不同的字母和字符),适应不同的排序和检索数据的方法。

  1. 字符集:字母和符号的集合
  2. 编码:某个字符集成员的内部表示
  3. 校对:规定字符如何比较的指令

MySQL的正常数据库活动(Select、Insert等),不需要操心太多。

27.2 使用字符集和校对顺序

 

查看所支持的字符集完整列表,使用以下语句:

Show Character set;

查看所支持校对的完整列表,使用以下语句:

Show Collation;

创建一个完整的

Create Table mytable

(column1 int,

column2 varchar(10)

)default character set hebrew

collate hebrew_general_ci;

28章 安全管理(P208)

28.1 访问控制

 

MySQL服务器的安全基础是:用户应该对他们需要的数据具有适当的访问权,既不能多也不能少。

MySQL可以通过可视化手段,添加一个用户,并且可以设置应有的权限

28.2 管理用户

 

MySQL用户账号和信息存储在名为mysql的MySQL数据库中。一般不需要直接访问mysql数据库和表,但有时需要直接访问。比如想要知道这个数据库有哪些用户时,就需要用到。

Use mysql;

Select user from user; ——返回的两个都是用户,拥有不同权限

28.2.1 创建用户账号

 

为了作为散列值指定口令,使用identified by,不然这个口令就是加密后的文本。

Create User ben identified by 'a213456'

更改名称

Rename User ben to ben222;

28.2.2 删除用户账号

 

为了删除一个用户账号(以及相关的权限),使用Drop User语句

Drop User ben222;

28.2.3 设置访问权限

 

新创建的用户没有访问权限,能登录MySQL,但看不到数据,不能执行任何操作。

Show Grants For ben

修改权限,crashcourse是全部权限

Grant Select On crashcourse.* To ben;

如果取消,则用Revoke,其他语句完全一样。

28.2.4 更改口令

 

Set Password=Password('n3w p@$$wOrd');

——这个先别用了,用过一次把我root的密码给改没了,再找回来浪费很多时间

29章 数据库维护(P216)

29.1 备份数据

 

  • 使用命令行实用程序mysqldump转储所有数据库内容到外部文件。在进行常规备份前这个实用程序应该正常工作,以便正确地备份转储文件。
  • 可用命令行实用程序mysqlhotcopy从一个数据库复制所有数据。
  • 可以使用MySQL的backup table或Select into outfile转储所有数据到某个外部文件。这两条语句都接受将要创建的系统文件名,此系统文件必须不存在,否则出错。数据可以通过Restore Table复原。

29.2 进行数据库维护

 

  • Analyze Table 表名,用来检查表键是否正确。

  • Check Table 表名,可用于多个表检查,发现和修复问题。在MyISAM表上对索引进行检查。
  • Changed检查自最后一次检查以来改动过的表。
  • Extended执行最彻底的检查。
  • Fast只检查未正常关闭的表。
  • Medium检查所有被删除链接并进行键检验。
  • Quick只进行快速扫描。
  • 如果MyISAM表访问产生不正确,可能需要Repair table来修复相应的表,如果经常使用,可能会有更大的问题要解决。
  • 如果从一个表中删除大量数据,应使用Optimize Table来收回所用的空间,优化性能。

29.3 诊断启动问题

 

在排除系统启动问题时,首先尽量使用手动启动服务器。在命令行中执行Mysqld启动。

  • --help显示帮助:一个选项列表
  • --safe-mode:装载减去某些最佳配置的服务器
  • --verbose:显示全文本消息(与--help联合使用)
  • --version:显示版本信息然后退出。

29.4 查看日志文件(P218)

 

  • 错误日志。

30章 改善性能

30.1 改善性能

 

在诊断应用的滞缓现象和性能问题时,性能不良的数据库(以及数据库查询)是最常见的原因

  1. MySQL使用show variables和show status查看配置
  2. MySQL一个多用户多线程的DBMS,经常执行多个任务。如果其中一个执行缓慢,则所有请求都执行缓慢。使用Show processlist显示所有活动进程(以及它们的线程ID和执行时间)。还可以用Kill命令终结某个特定的进程
  3. 有不止一个方法编写同一条Select语句,联结、并、子查询等,找到最佳方法
  4. 使用Explain语句让MySQL解释它将如何执行一条Select语句
  5. 存储过程执行得比一条一条地执行其中的各条MySQL语句块
  6. 应该总是使用正确的数据类型
  7. 不要检索比需求还要多的数据,比如Select* 除非真的要每一个列
  8. Select语句有多条OR条件,不如分开来用Union联合,会有极大的性能改进
  9. 索引改善数据检索的性能,但损害数据插入、删除和更新的性能。如果不经常搜索,可以不用索引
  10. Like很慢,所以最好使用Fulltext而不是Like
  11. 数据库是不断变化的实体,由于表的使用和内容的更改,优化和配置可能改变

MySQL语句的语法

C.1 Alter Table

 

用来更新已存在表的模式,创建新表用Create Table。详情第21章。

Alter Table 表名

(

Add column datatype null/not null,

Change column columns datatype null/not null,

Drop column,

...);

Alter Table student

add column other char(30) not null;

C.2 Commit

 

用来将事务处理写到数据库。详情第26章。可以理解为将事务立即执行。

Commit;

C.3 Create Index

 

用于在一个或多个列上创建索引。详情第21章。

Create Index 索引名 Create Index 索引名

On 表名(列 asc/desc,...) On 表名(id asc)

C.4 Create Procedure

 

创建存储过程,是可复用的代码块,可供后续使用和修改,详情第23章。

Create Procedure 存储过程名([参数])

Begin

...

End;

C.5 Create Table

 

创建数据库表,详情第21章。注意是表,不是库

Create Table 表名

(

column datatype null/not null,

...

id int not null auto_increment,

name varchar(30) not null,

primary key(id)

);engine=InnoDB

C.6 Create User

 

为系统添加新的用户账户。

Create User username[@hostname]

[identified by 密码 'password']

 

Create User ben identified by 'a213456'

C.7 Create View

 

创建一个或多个表上的新视图,视图就是一个比较直观化的表格,不能再编辑sql代码,只能查看。详情第22章。

Create View 视图名 as

Select s.id,s.name,s.course,s.grade,info.address,info.beizhu

From info,student as s

Where info.name=s.name

C.8 Delete

 

从表中删除一行或多行。详情第20章。

Delete from 表名

[Where ...];

C.9 Drop

 

永久地删除数据库对象(表、视图、索引等),详情见第21、22、23、24章。

Drop database|index|procedure|table|trigger|user|view

itemname;

C.10 Insert

 

给表插入一行,详情第19章。

Insert into 表名[(column,...)]

values(values1,values2,...);

C.11 Insert Select

 

插入Select的结果到一个表,详情见第19章。

Insert into tablename

select columns ...from tablename..

C.12 Rollback

 

撤销一个事务处理块,详情见第26章。

Rollback[to savepointname]

C.13 Savepoint

 

保留点,详情见第26章。

Savepoint sp1;

C.14 Select

 

Select用于从一个或多个表(视图)中检索数据,更多信息参考第4-17章节。

Select columnname,...

From tablename,...

Where

Group by

Having

Order by

C.15 Start Transaction

 

新的事务处理块的开始,详情见第26章。

Start Transaction;

C.16 Update

 

更新表中的一行或多行,详情见第20章。

Update student(表名)

Set name(列名)='小红改'

Where id=10

C.17 触发器trigger

 

在插入/删除/更新某个/些字段后,触发器可以会写入一些数据到新的表。

Create Trigger newproduct After Insert to products

For Each Row Select "一二三四";

删除触发器

Drop Trigger newproduct;

更新内容

Create Trigger updatevendor before update on vendors

for each row set New.列名=Upper(New.列名);

New.列名=Upper(New.列名)

C.18 Like和Regexp区别

 

比如原有的表结构如下

Select*from student where name Like "君" ——返回空白

Select*from student where name regexp "君" ——返回所有文字内带有的列,也就是1、2、3、11、12,一共5列

也就是说,Like匹配整个列,而不是匹配列里面的值。但是如果使用通配符,就可以匹配里面的值。

Select*from student where name Like "%君" ——返回梁君梁再改改改君。匹配前面全部,后面只匹配一个君字。

"%君%"如果用这个,前后都有%,返回1、2、3、11、12,一共5列

Select*from student where name Regexp "^.*君" ——使用占位符,shift+数字6,句号代表匹配任意,乘号匹配多个

Select*from student where name Regexp "^君" ——但如果使用这样的匹配,只返回君梁啊123