|
<
文章目录
1. 数据库操作
1.1显示数据库
1.2 创建数据库
CREATE DATABASE 数据库名 CHARSET='编码格式'
- mysql> CREATE DATABASE create_test CHARSET = 'utf8';
复制代码 1.3 利用数据库
1.4 查看当前数据库
利用 SELECT DATABASE() 查看当前利用的数据库。
- mysql> SELECT DATABASE();
- +-------------+
- | DATABASE() |
- +-------------+
- | create_test |
- +-------------+
复制代码 1.5 删除数据库
- mysql> DROP DATABASE create_test;
复制代码
2. 表操作
2.1 创建表
格式:
- CREATE TABLE [IF NOT EXISTS] `表名` (
- `字段名` 列类型 [属性] [索引] [注释],
- `字段名` 列类型 [属性] [索引] [注释],
- .......
- `字段名` 列类型 [属性] [索引] [注释]
- ) [表类型] [字符集设置] [注释]
复制代码 利用下面的语句创建示例中的 one_piece 表。
- mysql> CREATE TABLE one_piece
- -> (
- -> id CHAR(10) NOT NULL COMMENT '海贼团id',
- -> pirates CHAR(10) NOT NULL COMMENT '海贼团名称',
- -> name CHAR(10) NOT NULL COMMENT '海贼名',
- -> age INT(11) NOT NULL COMMENT '海贼年龄',
- -> post VARCHAR(10) NULL COMMENT '海贼团职位'
- -> );
复制代码 注意:创建表时,指定的表名必须不存在,否则会出错。
2.2 更新表
2.2.1 添加列
在刚才创建的 one_piece 表中添加一列 bounty (赏金)。
- mysql> ALTER TABLE one_piece
- -> ADD bounty INT(15);
复制代码 2.2.2 删除列
删除 bounty 列。
- mysql> ALTER TABLE one_piece
- -> DROP COLUMN bounty;
复制代码 2.3 查看表结构
- mysql> DESC one_piece;
- +---------+-------------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +---------+-------------+------+-----+---------+-------+
- | id | char(10) | NO | | NULL | |
- | pirates | char(10) | NO | | NULL | |
- | name | char(10) | NO | | NULL | |
- | age | int(11) | YES | | NULL | |
- | post | varchar(10) | YES | | NULL | |
- +---------+-------------+------+-----+---------+-------+
复制代码 2.4 查看表详细信息
\G 后面不能加“ ; ”。
- mysql> SHOW TABLE STATUS LIKE 'one_piece' \G
- *************************** 1. row ***************************
- Name: one_piece
- Engine: InnoDB
- Version: 10
- Row_format: Dynamic
- Rows: 0
- Avg_row_length: 0
- Data_length: 16384
- Max_data_length: 0
- Index_length: 0
- Data_free: 0
- Auto_increment: NULL
- Create_time: 2021-09-03 17:53:58
- Update_time: NULL
- Check_time: NULL
- Collation: utf8mb4_0900_ai_ci
- Checksum: NULL
- Create_options:
- Comment:
- 1 row in set (0.39 sec)
复制代码 2.5 重命名表
两种方法:
- ALTER TABLE 表名 RENAME [TO | AS] 新表名;
- RENAME TABLE 表名 TO 新表名;
用方法一将 Products 表更名为 new_Products ,再用方法二改返来。
- -- 方法一
- mysql> ALTER TABLE one_piece RENAME TO new_one_piece;
- -- 方法二
- mysql> RENAME TABLE new_one_piece TO one_piece;
复制代码 2.6 删除表
DROP TABLE 表名
- mysql> DROP TABLE one_piece;
复制代码 注意:在该表与其他表有关联时,Mysql 会阻止该表的删除。
3. 查询
3.1 查询多列
同时输出 name, age 列。
- mysql> SELECT name, age
- -> FROM one_piece;
复制代码 3.2 检索唯一值
利用 DISTINCT 关键字,查询字段 age 的唯一值。
- mysql> SELECT DISTINCT age
- -> FROM one_piece;
复制代码 3.3 限定输出
在 Mysql 中利用 LIMIT 关键字限定输出的数据。LIMIT 有两种常见用法:
- SELECT * FROM table LIMIT [offset], rows -- LIMIT 单独使用
- SELECT * FROM table LIMIT rows OFFSET [offset] -- 配合 OFFSET 使用
复制代码 offset:行开始的行的索引。0表示从第1行 开始显示(包括第1行),以此类推。
rows:数据显示的条数。
示例:
- SELECT * FROM one_piece LIMIT 5; -- 检索前5条数据
- --相当于
- SELECT * from one_piece LIMIT 0,5; -- 从第0行开始检索5条数据
- --相当于
- SELECT * FROM one_piece LIMIT 5 OFFSET 0; -- 从第0行开始检索5条数据,注意这里的LIMIT的5指代的是数量
复制代码 注:如果表中数据不足,即LIMIT设定的数过大,则只会检索到最后一行。
3.4 注释
三种注释方式
4. ORDER BY 排序
4.1 单列排序
利用 ORDER BY 子句。 ORDER BY 子句取一个或多个列的名字,据此对输出进行排序(默认升序)。
- mysql> SELECT name, age
- -> FROM one_piece
- -> ORDER BY age;
复制代码 **注意:**在指定一条 ORDER BY 子句时,应该保证它是 SELECT 语句中最后一条子句。
4.2 多列排序
- mysql> SELECT A, B
- -> FROM test
- -> ORDER BY A, B;
复制代码 在按多列排序时,仅在多个行具有相同的 A 值时 才按 B 进行排序。如果 A 列中所有的值都是 唯一的,则不会按 B 排序。
4.3 指定排序方向
ORDER 默认升序(从A到Z)排序。指定 DESC 关键字进行降序(从Z到 A)排序。
- mysql> SELECT age
- -> FROM one_piece
- -> ORDER BY age DESC;
复制代码 多列指定排序方向时,要利用逗号分隔。
- mysql> SELECT name, age
- -> FROM one_piece
- -> ORDER BY name DESC, age;
复制代码
5. WHERE 过滤数据
5.1 WHERE 子句操作符
操 作 符阐明操作符阐明=即是>大于、!=不即是>=大于即是不大于 FROM one_piece -> WHERE A BETWEEN 5 AND 10;[/code]
查询 字段 age 中 >=5 并且 SELECT name -> FROM one_piece -> WHERE name IS NULL;[/code]
6. 高级数据过滤
6.1 WHERE 组合过滤
利用 AND 、OR 操作符给 WHERE 子句添加附加条件。 AND 的优先级比 OR 要高,优先级高低 () 、 AND 、 OR。在利用的过程中要注意各个优先级的影响。
- mysql> SELECT age
- -> FROM one_piece
- -> WHERE A BETWEEN 5 AND 10;
复制代码 6.2 IN 操作符
IN 操作符用来指定条件范围,范围中的每个条件都可以进行匹配。(与 OR 的功能相同,但速度比 IN 慢)
- mysql> SELECT name
- -> FROM one_piece
- -> WHERE name IS NULL;
复制代码 6.3 NOT 操作符
WHERE 子句中的 NOT 操作符有且只有一个功能,那就是否定其后所跟的任何条件。
- mysql> SELECT name, age
- -> FROM one_piece
- -> WHERE(name = '索隆' OR name = '路飞')
- -> AND age >= 18;
复制代码
7. 通配符过滤
通配符搜索只能用于文本字段(字符串),非文本数据范例字段不能利用 通配符搜索。
在利用通配符过滤之前要先了解 LIKE , LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式或取值。
7.1 % 通配符
% 表示任何字符出现任意次数。例如,为了找出所有以 路 开始的 name。
- mysql> SELECT name, age
- -> FROM one_piece
- -> WHERE name IN ('索隆', '路飞')
复制代码 7.2 _ 通配符
通配符 _ 的用途与 % 一样也是匹配任意字符,但它只匹配单个字符,而不是多个字符。
- mysql> SELECT name
- -> FROM one_piece
- -> WHERE name NOT IN ('索隆', '路飞')
复制代码
8. 创建计算字段
8.1 拼接字段
下面将 name , sex 两列进行合并。并通过 AS 关键字进行给新列赋予别名。
- mysql> SELECT name, age
- -> FROM one_piece
- -> WHERE name LIKE '路';
复制代码 8.2 执行算数计算
通过 quantity (数量)、 price (价格)来计算 total_price (总价)
- mysql> SELECT name, age
- -> FROM one_piece
- -> WHERE name LIKE '乌_普';
复制代码
9. 函数
9.1 常用文本处理函数
[table]函数阐明LEFT(str, length)返回指定长度的字符串的左边部门RIGHT(str, length)返回指定长度的字符串右边部门LTRIM(str)去掉字符串左边的空格RTRIM(str)去掉字符串右边的空格LOWER(str)将字符串转换为小写UPPER(str)将字符串转换为大写LENGTH(str)返回字符串的长度利用 LENGTH(str) 获取字符串的长度。
- mysql> SELECT Concat(name, '(', sex, ')') AS new_column
- -> FROM one_piece;
复制代码 9.2 日期和时间处理函数
查询在 2000年 出生的职员信息。
- mysql> SELECT quantity, price,
- -> quantity * price AS total_price
- -> FROM test
复制代码 9.3 数值处理函数
函数阐明ABS()返回一个数的绝对值COS()返回一个角度的余弦SIN()返回一个角度的正弦TAN()返回一个角度的正切PI()返回圆周率EXP()返回一个数的指数值SQRT()返回一个数的平方根以 ABS() 函数为例
- mysql> SELECT name, LENGTH(name) AS length
- -> FROM one_piece;
复制代码
10. 数据聚集
10.1 聚集函数
函数阐明AVG()返回某列的匀称值COUNT()返回某列的行数MAX()返回某列的最大值MIN()返回某列的最小值SUM()返回某列值之和10.1.1 AVG() 函数
查询匀称 age 。
- mysql> SELECT *
- -> FROM test
- -> WHERE YEAR(brithday)=2000;
复制代码 10.1.2 COUNT() 函数
两种利用方式:
- COUNT(*) 对表中行的数目进行计数,包括空值。
- sql> SELECT ABS(-1);
- +---------+
- | ABS(-1) |
- +---------+
- | 1 |
- +---------+
复制代码
- COUNT(column) 对特定列中非 NULL 行进行计数。
- mysql> SELECT AVG(age) AS avg_age
- -> FROM one_piece
复制代码 10.1.3 MAX() & MIN() 函数
当 column 列为数值列, MAX(column) / MIN(column) 返回 column 列中的最大值 / 最小值。
当 column 列为文本数据, MAX(column) / MIN(column) 返回 column 列数据排序后的最后一行 / 最前面的行。
10.1.4 SUM() 函数
SUM() 用来返回指定列值的和(总计)(忽略列值为 NULL 的行)。
- mysql> SELECT COUNT(*) AS num_person
- -> FROM one_piece;
复制代码 10.2 组合聚集函数
计算 one_piece 表中数据的条数,年事的最小值、最大值和匀称值。
- mysql> SELECT COUNT(name) AS num_name
- -> FROM one_piece;
复制代码
11. 数据分组
11.1 数据分组
利用分组将数据分为多个逻辑组, 对每个组进行聚集计算。
例:统计各个海贼团( pirates )的人数。
- mysql> SELECT SUM(price * quantity) AS total_price
- -> FROM test
复制代码 group by 注意事项:
- GROUP BY 可以嵌套利用。
- GROUP BY 子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在 SELECT 中利用表达式,则必须在 GROUP BY 子句中指定相同的表达式。不能利用别名。
- 除聚集计算语句外,SELECT 语句中的每一列都必须在 GROUP BY 子句 中给出。
- 如果分组列中包含具有 NULL 值的行,则 NULL 将作为一个分组返回。 如果列中有多行 NULL 值,它们将分为一组。
- GROUP BY 子句必须出现在 WHERE 子句之后,ORDER BY 子句之前。
11.2 过滤分组
利用 HAVING 子句在数据分组后进行过滤。
查询海贼团人数在500人以上的 海贼团名称 及 人数。
- mysql> SELECT COUNT(*) AS num_person,
- -> MIN(age) AS age_min,
- -> MAX(age) AS age_max,
- -> AVG(age) AS age_avg
- -> FROM one_piece;
复制代码 WHERE 与 HAVING 的主要区别:
- WHERE 在数据分组前进行过滤,HAVING 在数据分组后进行过滤。
SELECT子句顺序:
子句阐明是否必须利用SELECT要返回的列或表达式是FROM从中检索数据的表仅在从表选择数据时利用WHERE行级过滤否GROUP BY分组阐明仅在按组计算聚集时利用HAVING组级过滤否ORDER BY输出排序顺序否
12. 子查询
12.1 利用子查询进行过滤
现在查询 草帽海贼团 的排名信息。
- mysql> SELECT pirates, COUNT(*) AS num_person
- -> FROM one_piece
- -> GROUP BY pirates;
复制代码 注意:
- 在 SELECT 语句中,子查询总是从内向外处理。
- 作为子查询的 SELECT 语句只能查询单个列。检索多个列会报错。
12.2 作为计算字段利用子查询
查询海贼团排名和任务信息,首先从 one_piece 表中根据 id 检索出排名信息,再统计每个冒险团的人数。
- mysql> SELECT pirates, COUNT(*) AS num_person
- -> FROM one_piece
- -> GROUP BY pirates
- -> HAVING COUNT(*) >= 500;
复制代码 注意:上面的例子中利用的是 oe.id 和 ro.id ,而不是直接利用 id ,因为在两个表中都有 id 列,在有大概混淆列名时必须利用这种语法。
13. 表联结
13.1 自联结
假如现在有人不知道 乔巴 所属的海贼团, 想要知道 乔巴 所属海贼团的所有成员名称与赏金。
先看一下子查询的方式:
- mysql> SELECT rank
- -> FROM rank_info
- -> WHERE id IN (SELECT id
- -> FROM one_piece
- -> WHERE pirates = '草帽海贼团');
复制代码 接下来利用自联结的方式:
- mysql> SELECT rank,
- -> (SELECT COUNT(*)
- -> FROM one_piece AS oe
- -> WHERE oe.id = ro.id) AS num_person
- -> FROM rank_info AS ro
- -> ORDER BY rank;
复制代码 通常情况下,自联结的方式比子查询的方式要快很多。
13.2 等值联结
联结是一种机制,用来在一条 SELECT 语句 中关联表,因此称为联结。利用特别的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。联结不是物理实体。换句话说,它在实际的数据库表 中并不存在。它只在查询执行期间存在。
两表 table1, table2 中数据如下:
- mysql> SELECT name, bounty
- -> FROM one_piece
- -> WHERE pirates = (SELECT pirates
- -> FROM one_piece
- -> WHERE name = '乔巴');
复制代码 现在通过表联结,获取两个表中的数据。
- mysql> SELECT c1.name, c1.bounty
- -> FROM Customers AS c1, Customers AS c2
- -> WHERE c1.pirates = c2.pirates
- -> AND c2.name = '乔巴';
复制代码 注意:上例中WHERE 中限定了联结条件,如果没有条件的话,返回的结果就是两表的笛卡尔积,返回 6 × 9 共 54条数据
13.3 内联结
上面的联结准确来说是等值联结,也可以称为内联结,它另有另一种语法。返回的结果以上面相同。
- table1 table2
- +------+------+------+ +------+------+------+
- | A | B | C | | C | D | E |
- +------+------+------+ +------+------+------+
- | 1 | 2 | 3 | | 2 | 3 | 4 |
- | 4 | 5 | 6 | | 6 | 7 | 8 |
- +------+------+------+ +------+------+------+
复制代码 一般内联结可以用如下图进行表示,取两个表关联字段相同的部门。
13.4 自然联结
自然连接是一种特别的等值连接,它在两个关系表中自动比力相同的属性列,无须添加连接条件,并且在结果中消除重复的属性列。
- mysql> SELECT *
- -> FROM table1 AS t1, table2 AS t2
- -> WHERE t1.C = t2.C;
- +------+------+------+------+------+------+
- | A | B | C | C | D | E |
- +------+------+------+------+------+------+
- | 4 | 5 | 6 | 6 | 7 | 8 |
- +------+------+------+------+------+------+
复制代码 13.5 外联结
13.5.1 左外联结
左外联结,左表( table1 )的记录将会全部表示出来,而右表( table2 )只会显示符合搜索条件的记录。右表记录不足的地方均为 NULL 。
- mysql> SELECT *
- -> FROM table1 AS t1 INNER JOIN table2 AS t2
- -> ON t1.C = t2.C;
- +------+------+------+------+------+------+
- | A | B | C | C | D | E |
- +------+------+------+------+------+------+
- | 4 | 5 | 6 | 6 | 7 | 8 |
- +------+------+------+------+------+------+
复制代码 13.5.2 右外联结
右外联结,右表( table2 )的记录将会全部表示出来,而右左表( table1 )只会显示符合搜索条件的记录。左表记录不足的地方均为 NULL 。
- mysql> SELECT *
- -> FROM table1 AS t1 NATURAL JOIN table2 t2;
- +------+------+------+------+------+
- | C | A | B | D | E |
- +------+------+------+------+------+
- | 6 | 4 | 5 | 7 | 8 |
- +------+------+------+------+------+
复制代码 13.6 四种联结对比图
14. 插入数据
14.1 插入完整行
利用 INSERT 插入完整行它要求指定 表名和插入到新行中的值。
- mysql> SELECT *
- -> FROM table1 AS t1 LEFT JOIN table2 AS t2
- -> ON t1.C = t2.C;
- +------+------+------+------+------+------+
- | A | B | C | C | D | E |
- +------+------+------+------+------+------+
- | 4 | 5 | 6 | 6 | 7 | 8 |
- | 1 | 2 | 3 | NULL | NULL | NULL |
- +------+------+------+------+------+------+
复制代码 注意:
- 必须每列提供一个值,空值利用NULL
- 各列必须以它们在表界说中出现的序次填充
14.2 插入部门行
INSERT 保举的插入方法是明白给出表的列名。这样还可以省略列,即只给某些列提供值,给其他列不提供值。
省略的列必须满意以下某个条件:
- 该列界说为允许 NULL 值(无值或空值)。
- 在表界说中给出默认值(如果不给出值,将利用默认值)。
如果表中不允许有 NULL 值大概默认值,这时却省略了表中的值, DBMS 就会产生错误消息,相应的行不能成功插入。
现在同样在 one_piece 表中插入一行。
- mysql> SELECT *
- -> FROM table1 AS t1 RIGHT JOIN table2 AS t2
- -> ON t1.C = t2.C;
- +------+------+------+------+------+------+
- | A | B | C | C | D | E |
- +------+------+------+------+------+------+
- | 4 | 5 | 6 | 6 | 7 | 8 |
- | NULL | NULL | NULL | 2 | 3 | 4 |
- +------+------+------+------+------+------+
复制代码 不管利用哪种INSERT 语法,VALUES 的数目都必须正确。如果不提供列 名,则必须给每个表列提供一个值;如果提供列名,则必须给列出的每个列一个值。否则,就会产生一条错误消息,相应的行不能成功插入。
14.3 从一个表复制到另一个表
有一种数据插入倒霉用 INSERT 语句。要将一个表的内容复制到一个全新的表(运行中创建的表)。
- mysql> INSERT INTO one_piece
- -> VALUES('1',
- -> '草帽海贼团',
- -> '路飞',
- -> 'age',
- -> '团长',
- -> '1500000000');
复制代码
- 任何 SELECT 选项和子句都可以利用,包括 WHERE 和 GROUP BY。
- 可利用联结从多个表插入数据。
- 不管从多少个表中检索数据,数据都只能插入到一个表中。
主要用途:它是试验新 SQL 语句前进行表复制的很好工具。先进行复制,可在复制的数据上测试 SQL 代码,而不会影响实际的数据。
15.更新数据
利用 UPDATE 语句,更新(修改)表中的数据。
有两种利用 UPDATE 的方式:
利用时要明白是 更新特定行 还是 更新所有行。
UPDATE 语句中可以利用子查询,使得能用 SELECT 语句检索出的数据 更新列数据。
15.1 更新单行单列
将 路飞 的赏金更新为 10000000000
- mysql> INSERT INTO one_piece(id,
- -> pirates,
- -> name)
- -> VALUES('1',
- -> '草帽海贼团',
- -> '路飞');
复制代码 15.2 更新单行多列
在更新多个列时,只需要利用一条 SET 下令,每个“列=值”对之间用逗号分隔(最后一列之后不用逗号)。
- mysql> CREATE TABLE one_pieceCopy AS
- -> SELECT * FROM one_piece;
复制代码 15.3 更新所有行
倒霉用 WHERE 限定条件,即更新表中所有行。
- mysql> UPDATE one_piece
- -> SET bounty = 10000000000
- -> WHERE name = '路飞';
复制代码 15.4 删除列中的值
假如表界说允许 NULL 值,要删除某个列的值,可设置它为 NULL。(要注意删除列值(保存列结构)和删除列(完全删除)的区别)
- mysql> UPDATE one_piece
- -> SET bounty = 10000000000,
- -> age = '19'
- -> WHERE name = '路飞';
复制代码
16. 删除数据
利用 DELETE 语句,删除表中的数据。
有两种利用 DELETE 的方式:
利用时要明白是 删除特定行 还是 删除所有行。
16.1 删除单行
删除 one_piece 表中 name 为 路飞 的行。
- mysql> UPDATE one_piece
- -> SET bounty = 10000000000,
- -> age = '19'
复制代码 16.2 删除所有行
删除 Customers 中的所有行。不删除表自己。
- mysql> UPDATE one_piece
- -> SET bounty = NULL
- -> WHERE name = '路飞';
复制代码 如果想从表中删除所有行,保举利用 TRUNCATE TABLE 语句,它完成相同的工作,而速度更快(因为不记录数据的变动)。
但要注意: TRUNCATE 属于数据界说语言( DDL ),且 TRUNCATE 下令执行后无法回滚,利用 TRUNCATE 下令之前最好对当前表中的数据做备份。
- mysql> DELETE FROM one_piece
- -> WHERE name = '路飞';
复制代码
17.存储过程
17.1 为什么利用存储过程
优点:
- 通过把 “某个处理” 封装在一个易用的单位中,可以简化复杂的操作
- 由于不要求反复建立一系列处理步骤,因而保证了数据的一致性。
- 简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变 化,那么只需要更改存储过程的代码。利用它的职员甚至不需要知道 这些变革。
- 因为存储过程通常以编译过的形式存储,所以DBMS处理下令所需的 工作量少,提高了性能。
简单来说,利用存储过程有三个主要的好处:简单、安全、高性能。
17.2 创建存储过程
我们来看一个简单的存储过程例子,对 草帽海贼团 人数进行计数。
- mysql> DELETE FROM one_piece;
复制代码 在界说过程时,利用 DELIMITER $$ 下令将语句的竣事符号从分号 ; 临时改为 $$,使得过程体中利用的分号被直接传递到服务器,而不会被 Mysql 解释。
利用 CALL 存储过程名(参数) 来调用存储过程。
- mysql> TRUNCATE TABLE one_piece;
复制代码 17.3 存储过程体
存储过程体包含了在过程调用时必须执行的语句,例如:dml、ddl语句,if-then-else和while-do语句、声明变量的declare语句等。
过程体格式:以begin开始,以end竣事(可嵌套)
- mysql> DELIMITER $$
- mysql> CREATE PROCEDURE personCount()
- -> BEGIN
- -> SELECT COUNT(*) AS num_person
- -> FROM one_piece
- -> WHERE pirates = '草帽海贼团';
- -> END$$
复制代码 注意:每个嵌套块及此中的每条语句,必须以分号竣事,表示过程体竣事的 begin-end 块(又叫做复合语句 compound statement ),则不需要分号。
17.4 存储过程参数
存储过程可以有0个或多个参数,用于存储过程的界说。
3种参数范例:
- IN (输入参数):表示调用者向过程传入值(传入值可以是字面量或变量)
- OUT (输出参数):表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
- INOUT (输入输出参数):既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
17.4.1 IN输入参数
- mysql> DELIMITER ;
- mysql> CALL personCount();
复制代码 虽然 p_in 在存储过程中被修改,但并不影响 @p_in 的值,因为 in_test 只接受输入参数,并不输出参数,所以相当于在函数内改变,但并未将这个值输出给 @p_in 。
17.4.2 OUT输入参数
- BEGIN
- BEGIN
- BEGIN
- statements;
- END
- END
- END
复制代码 第一个返回结果为 NULL 是因为 OUT 是向调用者输出参数,不吸收输入的参数,所以第一次查询时 p_out 还未赋值,所以是 NULL 。最后 @p_out 变量的值变为2是因为调用了 out_test 存储过程,输出参数,改变了 p_out 变量的值。
17.4.3 INOUT输入输出参数
- mysql> DELIMITER $$
- mysql> CREATE PROCEDURE in_test(IN p_in INT)
- -> BEGIN
- -> SELECT p_in; -- 第一次查询
- -> SET p_in = 2; -- 修改p_in的值
- -> SELECT p_in; -- 第二次查询
- -> END$$
-
- mysql> DELIMITER ;
- mysql> SET @p_in = 1;
- mysql> CALL in_test(@p_in);
- +------+
- | p_in |
- +------+
- | 1 |
- +------+
- +------+
- | p_in |
- +------+
- | 2 |
- +------+
- mysql> SELECT @p_in;
- +-------+
- | @p_in |
- +-------+
- | 1 |
- +-------+
复制代码 调用 inout_test 存储过程,既接受了输入的参数,也输出参数, @p_inout 的值被改变。
17.5 删除存储过程
利用 DROP PROCEDURE 来删除存储过程。
- mysql> DELIMITER $$
- mysql> CREATE PROCEDURE out_test(OUT p_out INT)
- -> BEGIN
- -> SELECT p_out; -- 第一次查询
- -> SET p_out = 2; -- 修改p_out的值
- -> SELECT p_out; -- 第二次查询
- -> END$$
- mysql> DELIMITER ;
- mysql> SET @p_out = 1;
- mysql> CALL out_test(@p_out);
- +-------+
- | p_out |
- +-------+
- | NULL |
- +-------+
- +-------+
- | p_out |
- +-------+
- | 2 |
- +-------+
- mysql> SELECT @p_out;
- +--------+
- | @p_out |
- +--------+
- | 2 |
- +--------+
复制代码
18.管理事件处理
18.1 事件处理
事件处理(transaction processing)是一种机制, 用来管理必须成批执行的SQL` 操作,保证数据库不包含不完整的操作结果。利用事件处理,可以保证一组操作不会中途停止,它们要么完全执行,要么完全不执行(除非明白指示)。如果没有错误发生,整组语句提交给(写到)数据库表;如果发生错误,则进行回退(撤销),将数据库恢复到某个已知且安全的状态,以此来维护数据库的完整性。
事件处理术语:
- 事件(transaction):指一组 SQL 语句;
- 回退(rollback):指撤销指定 SQL 语句的过程;
- 提交(commit):指将未存储的 SQL 语句结果写入数据库表;
- 保存点(savepoint):指事件处理中设置的临时占位符(placeholder), 可以对它发布回退(与回退整个事件处理不同)。
事件处理用来管理 INSERT、UPDATE 和 DELETE 语句。不能回退 SELECT 语句(回退 SELECT 语句也没有必要),也不能回退 CREATE 或 DROP 操 作。事件处理中可以利用这些语句,但进行回退时,这些操作也不撤销。
一般来说,事件是必须满意4个条件( ACID )::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、长期性(Durability)。
- 原子性: 一个事件( transaction )中的所有操作,要么全部完成,要么全部不完成,不会竣事在中间某个环节。事件在执行过程中发生错误,会被回滚( Rollback )到事件开始前的状态,就像这个事件从来没有执行过一样。
- 一致性: 在事件开始之前和事件竣事以后,数据库的完整性没有被粉碎。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性: 数据库允许多个并发事件同时对其数据进行读写和修改的能力,隔离性可以防止多个事件并发执行时由于交叉执行而导致数据的不一致。事件隔离分为不同级别,包括读未提交( Read uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable)。
- 长期性: 事件处理竣过后,对数据的修改就是永久的,即便体系故障也不会丢失。
在 MySQL 下令行的默认设置下,事件都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事件务须利用下令 BEGIN 或 START TRANSACTION,大概执行下令 SET AUTOCOMMIT=0,用来禁止利用当前会话的自动提交。
18.2 控制事件处理
- BEGIN / START TRANSACTION :显式地开启一个事件;
- COMMIT / COMMIT WORK :提交事件,使已对数据库进行的所有修改成为永久性的;
- ROLLBACK / ROLLBACK WORK :回滚会竣事用户的事件,并撤销正在进行的所有未提交的修改;
- SAVEPOINT :SAVEPOINT 允许在事件中创建一个生存点,一个事件中可以有多个 SAVEPOINT;
- RELEASE SAVEPOINT :删除一个事件的生存点,当没有指定的生存点时,执行该语句会抛出一个异常;
- ROLLBACK TO :把事件回滚到标记点;
- SET TRANSACTION :用来设置事件的隔离级别。InnoDB 存储引擎提供事件的隔离级别有 READ UNCOMMITTED(读未提交)、READ COMMITTED(读已提交,项目中常用)、REPEATABLE READ(可重复读,Mysql 默认隔离级别) 和 SERIALIZABLE(串行化)。
简单示例:
- mysql> DELIMITER $$
- mysql> CREATE PROCEDURE inout_test(INOUT p_inout INT)
- -> BEGIN
- -> SELECT p_inout; -- 第一次查询
- -> SET p_inout = 2; -- 修改p_inout的值
- -> SELECT p_inout; -- 第一次查询
- -> END$$
-
- mysql> DELIMITER ;
- mysql> SET @p_inout = 1;
- mysql> CALL inout_test(@p_inout);
- +---------+
- | p_inout |
- +---------+
- | 1 |
- +---------+
- +---------+
- | p_inout |
- +---------+
- | 2 |
- +---------+
- mysql> SELECT @p_inout;
- +----------+
- | @p_inout |
- +----------+
- | 2 |
- +----------+
复制代码
18.3 事件隔离级别
先看一下如何查看事件隔离级别。
- mysql> DROP PROCEDURE in_test;
复制代码 在 Mysql 下事件的隔离级别有四种,由低到高依次为 Read uncommitted 、Read committed 、Repeatable read (默认)、Serializable ,这四个级别中的后三个级别可以逐个解决脏读 、不可重复读 、幻读的问题。
18.3.1 脏读
对于两个事件T1与T2,T1读取了已经被T2更新但是还没有提交的字段之后,若此时T2回滚,T1读取的内容就是临时并且无效的。
示例:
打开两个Mysql客户端,分别执行下面操作,查询当前会话的隔离级别(默认 REPEATABLE READ )。修改当前会话隔离级别为( READ UNCOMMITTED )。全局事件隔离级别仍旧为 REPEATABLE READ 。
- mysql> use test;
- mysql> CREATE TABLE transaction_test(id int(5)) ENGINE = INNODB; # 创建数据表
-
- mysql> SELECT * FROM transaction_test;
- Empty set (0.01 sec)
- mysql> BEGIN; # 开始事务
-
- mysql> INSERT INTO runoob_transaction_test VALUE(1);
-
- mysql> INSERT INTO runoob_transaction_test VALUE(2);
-
- mysql> COMMIT; # 提交事务
-
- mysql> SELECT * FROM transaction_test;
- +------+
- | id |
- +------+
- | 1 |
- | 2 |
- +------+
- mysql> BEGIN; # 开始事务
- mysql> INSERT INTO transaction_test VALUES(3);
- mysql> SAVEPOINT first_insert; # 声明一个保存点
- mysql> INSERT INTO transaction_test VALUES(4);
- mysql> SAVEPOINT second_insert; # 声明一个保存点
- mysql> INSERT INTO transaction_test VALUES(5);
- mysql> ROLLBACK TO second_insert; # 回滚到 second_insert 保存点
- mysql> SELECT * FROM transaction_test; # 因为回滚所以数据没有插入
- +------+
- | id |
- +------+
- | 1 |
- | 2 |
- | 3 |
- | 4 |
- +------+
- mysql> ROLLBACK TO first_insert;
- mysql> SELECT * FROM transaction_test;
- +------+
- | id |
- +------+
- | 1 |
- | 2 |
- | 3 |
- +------+
- mysql> COMMIT; # 执行 COMMIT 或 ROLLBACK 后保存点自动释放
复制代码 之后黑框用来做更新,白框用来查询。
由于黑框的 ④ 回滚,白色背景的客户端中 ③ 读取的数据就是临时并且无效的。即脏读。
18.3.2 不可重复读
对于两个事件T1和T2,T1读取了一个字段,然后T2更新了该字段并提交之后,当T1再次读取的时间,结果不一致的情况发生。
由于黑框的更新操作,白框出现两次读取的结果不一致。
18.3.3 幻读
对于两个事件T1、T2,T1从表中读取数据,然后T2进行了INSERT操作并提交,当T1再次读取的时间,结果不一致的情况发生。
由于黑框的插入操作,白框出现两次读取的结果不一致。
几种现象在各隔离级别中出现的大概性:
隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)未提交读(Read uncommitted)大概大概大概已提交读(Read committed)不大概大概大概可重复读(Repeatable read)不大概不大概大概可串行化(Serializable )不大概不大概不大概
19. 游标
SQL 检索操作返回结果集,简单地利用 SELECT 语句,没有办法得到第一行、下一行或前 10 行。有时,需要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。游标(cursor)是一个存储在 DBMS 服务器上的数据库查询, 它不是一条 SELECT 语句,而是被该语句检索出来的结果集。在存储了 游标之后,应用程序可以根据需要滚动或欣赏此中的数据。
19.1 利用游标
游标利用的步骤:
- 在利用游标前,必须声明(界说)它。这个过程实际上没有检索数据, 它只是界说要利用的 SELECT 语句和游标选项。
- 一旦声明,就必须打开游标以供利用。这个过程用前面界说的 SELECT 语句把数据实际检索出来。
- 对于填有数据的游标,根据需要取出(检索)各行。
- 在竣事游标利用时,必须关闭游标,大概的话,释放游标。
声明游标后,可以根据需要频繁地 打开或关闭 游标。在游标打开时,可根据需要频繁地执行 取 操作。
注意:不像多数DBMS,MySQL游标只能用于存储过程(和函数)。
19.2 创建游标
利用 DECLEAR 来创建游标,DECLARE 命名游标,并界说相应的 SELECT 语句,根据需要带 WHERE 和 其他子句。
下面的语句界说了名为 ordernumbers 的游标,利用了可以检索所有订单的 SELECT 语句。
Order表中的信息:
- # 查看默认事务隔离级别(session)
- select @@transaction_isolation;
- # 查看当前会话的隔离级别
- select @@session.transaction_isolation;
- # 查看全局的事务隔离级别
- select @@global.transaction_isolation;
复制代码 这个存储过程中,利用 DECLARE 语句用来界说和命名游标。存储过程处理完成后,游标就消失(因为它局限于存储过程)。
19.3 利用游标数据
利用 OPEN 语句来打开游标,CLOSE 语句关闭游标,在一个游标被打开后,可以利用 FETCH 语句分别访问它的每一行。FETCH 指定检索的数据(所需的列),数据存储的位置(界说的变量)。 它还向前移动游标中的内部行指针,使下一条 FETCH 语句检索下一行(不重复读取同一行)。
- mysql> SELECT @@session.transaction_isolation;
- +-------------------------+
- | @@transaction_isolation |
- +-------------------------+
- | REPEATABLE-READ |
- +-------------------------+
- mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; # 修改会话隔离级别
- mysql> SELECT @@session.transaction_isolation; # 当前会话隔离级别已修改
- +---------------------------------+
- | @@session.transaction_isolation |
- +---------------------------------+
- | READ-UNCOMMITTED |
- +---------------------------------+
- mysql> SELECT @@global.transaction_isolation; # 全局事务隔离级别未修改
- +--------------------------------+
- | @@global.transaction_isolation |
- +--------------------------------+
- | REPEATABLE-READ |
- +--------------------------------+
复制代码
此中 FETCH 用来检索当前行的 order_num 列(将自动从第一行开始)到一个名为 num 的局部变量中,并将查询 num 的结果。由于只检索到第一行,所以 num 的值为 ‘20005’。
下面,循环检索数据,从第一行到最后一行。
- DROP PROCEDURE IF EXISTS processorder;
- CREATE PROCEDURE processorder()
- BEGIN
- -- 定义游标
- DECLARE ordernumbers CURSOR
- FOR
- SELECT order_num FROM orders;
- END;
复制代码
循环了结果集的所有行,所以 num 的值是最后一行的数据。
与上一个例子不同之处是,这个例子的 FETCH 是在 REPEAT 内,因此它反复执行直到 done 为真。
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done=true;
这条语句界说了一个 CONTINUE HANDLER,它是在条件出现时被执行的代码。这里,它指出当 SQLSTATE '02000' 出现时,SET done=true。SQLSTATE '02000'是一个未找到条件,当 REPEAT 由于没有更多的行供循环而不能继承时,出现这个条件。
19.4 游标的优缺点
优点:游标是面向聚集与面向行的计划思想之间的一种桥梁,因为游标是针对行操作的,所以对从数据库中 SELECT 查询得到的每一行可以进行分开的独立的相同或不同的操作,是一种分离的思想。可以满意对某个结果行进行特别的操作。如基于游标位置的增编削查能力。
缺点:
20. 约束
20.1 约束
DBMS 通过在数据库表上施加约束来实验引用完整性。大多数约束是在表界说中界说的,用 CREATE TABLE 或是 ALTER TABLE 语句。
20.2 主键
主键是一种特别的约束,用来保证一列(或 一组列)中的值是唯一的,而且永不改动。没有主键,要安全地 UPDATE 或 DELETE 特定行而不影响其他行会 非常困难。
主键的条件:
- 任意两行的主键值都不相同。
- 每行都具有一个主键值(即列中不允许 NULL 值)。
创建表时界说主键。
- DROP PROCEDURE IF EXISTS processorder;
- CREATE PROCEDURE processorder()
- BEGIN
- -- 定义局部变量
- DECLARE num INT;
- -- 定义游标
- DECLARE ordernumbers CURSOR
- FOR
- SELECT order_num FROM orders;
- -- 打开游标
- OPEN ordernumbers;
- -- 获取第一行数据
- FETCH ordernumbers INTO num;
- -- 查询结果
- SELECT num;
- -- 关闭游标
- CLOSE ordernumbers;
- END;
- CALL processorder();
复制代码 利用 ALTER TABLE 添加主键。
- DROP PROCEDURE IF EXISTS processorder;
- CREATE PROCEDURE processorder()
- BEGIN
- -- 定义局部变量
- DECLARE done BOOLEAN DEFAULT false;
- DECLARE num INT;
- -- 定义游标
- DECLARE ordernumbers CURSOR
- FOR
- SELECT order_num FROM orders;
- -- 定义CONTINUE HANDLER
- DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=true;
- -- 打开游标
- OPEN ordernumbers;
- -- 循环所有行
- REPEAT
- -- 获取第一行数据
- FETCH ordernumbers INTO num;
- -- 结束循环
- UNTIL done END REPEAT;
- -- 查询结果
- SELECT num;
- -- 关闭游标
- CLOSE ordernumbers;
- END;
- CALL processorder();
复制代码 删除主键约束。
- CREATE TABLE teacher
- (
- id INT(11) PRIMARY KEY,
- teacher_name VARCHAR(10)
- );
复制代码
20.3 外键
外键是表中的一列,其值必须列在另一表的主键中。外键是保证引用完 整性的极其重要部门。
下面新建 student 表并添加外键 teacher_id 与 teacher 表中的主键 id 进行关联。
在创建表的时界说外键。
- ALTER TABLE teacher
- ADD CONSTRAINT PRIMARY KEY(id);
复制代码 利用 ALTER TABLE 添加外键。
- ALTER TABLE teacher DROP PRIMARY KEY;
复制代码 利用外键可以有效地防止意外删除,比如在上面两表中如果删除 teacher 表中的信息,如果该 id 在 student 表中也有出现,那么 Mysql 会防止删除操作。固然也可以启用级联删除的特性,那么在删除时就会删除所有相关信息。
删除外键。
- CREATE TABLE student
- (
- stu_id INT(11) PRIMARY KEY,
- teacher_id INT(11) REFERENCES teacher(id),
- stu_name VARCHAR(10)
- );
复制代码
20.4 唯一约束
唯一约束用来保证一列(或一组列)中的数据是唯一的。它们雷同于主 键,但存在以下重要区别。
- 表可包含多个唯一约束,但每个表只允许一个主键。
- 唯一约束列可包含 NULL 值。
- 与主键不一样,唯一约束不能用来界说外键。
在创建表的时界说唯一约束。
- ALTER TABLE teacher
- ADD CONSTRAINT PRIMARY KEY(id);
复制代码 利用 ALTER TABLE 添加唯一约束。
- ALTER TABLE student DROP FOREIGN KEY teacher_id_id;
复制代码 删除唯一性约束。
- CREATE TABLE student
- (
- stu_id INT(11) PRIMARY KEY,
- teacher_id INT(11) REFERENCES teacher(id),
- stu_name VARCHAR(10)
- );
复制代码
20.5 检查约束
检查约束用来保证一列(或一组列)中的数据满意一组指定的条件。
常见用途:
下面创建一个检查约束来限定性别列只能输入男、女。
在创建表的时界说检查约束。
- ALTER TABLE student
- ADD CONSTRAINT unique_id UNIQUE(stu_id);
复制代码 利用 ALTER TABLE 添加检查约束。
- ALTER TABLE student DROP INDEX unique_id;
复制代码 删除检查约束。
- CREATE TABLE student
- (
- stu_id INT(11) PRIMARY KEY,
- gender VARCHAR(1) CHECK(gender IN('男', '女'))
- );
复制代码
21. 索引
索引用来排序数据以加速搜索和排序操作的速度。主键数据总是排序的, 因此,按主键检索特定行总是一种快速有效的操作。但是,搜索其他列中的值通常效率不高。这时间我们可以利用索引,在一个或多个列上界说索引,使 DBMS生存其内容的一个排过序的列表。在界说了索引后,DBMS 以利用书的索引雷同的方法利用它。DBMS 搜索排过序的索引,找出匹配的位置,然后检索这些行。
索引特点:
- 索引提高检索的性能,但降低了数据增编削的性能。 在执行这些操作时,DBMS 必须动态地更新索引。
- 索引数据大概要占用大量的存储空间。
- 并非所有数据都适合做索引。取值不多的数据(如地区)不如具有更多大概值的数据(如姓名),可以或许更加体现索引的代价。
- 索引用于数据过滤和数据排序。如果你经常以某种特定的顺序排序数据,则该数据大概适合做索引。
- 可以在索引中界说多个列(例如,国家 + 城市)。
21.1 普通索引
在创建表的时创建普通索引。
- ALTER TABLE student ADD CONSTRAINT check_gender CHECK(gender in ('男', '女'));
复制代码 直接创建。
- ALTER TABLE student DROP CHECK check_gender;
复制代码 修改表时创建。
- DROP TABLE IF EXISTS student;
- CREATE TABLE student
- (
- id INT(11),
- stu_name VARCHAR(10)
- )
复制代码 删除索引。
- CREATE INDEX stu_id ON student(id);
复制代码
21.2 唯一索引
唯一索引列值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一。究竟上,在许多场合,创建唯一索引的目的往往不是提高访问速度,而是为了制止数据出现重复。
- ALTER TABLE student ADD INDEX stu_id(id);
复制代码
21.3 全局索引
全文索引只能作用在 CHAR、VARCHAR、TEXT、范例的字段上。创建全文索引需要利用 FULLTEXT 参数进行约束。
- DROP INDEX stu_id ON student;
复制代码
21.4 多列索引
多列索引,即在数据表的多个字段上创建索引。
- CREATE UNIQUE INDEX stu_id ON student(id);
复制代码 在多列索引中,只有查询条件中利用了这些字段中的第一个字段(即上面示例中的 stu_name 字段),索引才会被利用(最左前缀’原则)。如果没有用到第一字段,则索引不起任何作用。
- CREATE FULLTEXT INDEX s_name ON student(stu_name);
复制代码 这就是本文所有的内容了,如果感觉还不错的话。❤ 点个赞再走吧!!!❤
后续会继承分享各种干货,如果感兴趣的话可以点个关注不迷路哦~。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
|