MySQL的快速入门
什么是SQL
?
SQL(Structured Query Language)
是结构化查询语言的简称,是⼀种数据库查询和程序设计语言, 存取用于数据以及查询、更新和管理关系数据库。
常见的SQL分类:
DDL [ Data Definition Language ]
数据定义语言,用来维护存储数据的结构,代表指令:create, drop, alter
DML [ Data Manipulation Language ]
数据操纵语言,用来对数据进行操作,代表指令:insert,delete,update,select
DCL [ Data Control Language ]
数据控制语言,主要负责权限管理和事务,代表指令:grant,revoke,commit
在开始前学习前,我们应当对一些知识约定具有了解:
[]
中的内容是可选项,可以省略不写
{}
中的内容表示必须要写
|
是或的意思,表示任选一个
mysql中对sql关键字的大小写不敏感
下面的操作中,我们用大写来标记SQL中的关键字
,当然关键字也可以采用小写来使用.
库的操作
1. 查看数据库
语法
SHOW databases;
示例
-- 查看数据库
show databases;
2. 选择数据库
语法
USE 数据库名;
示例
-- 选择instance_db数据库使用
use instance_db;
3. 创建数据库
语法
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] 要创建的数据库名 [create_option]...create_option: [DEFAULT] {CHARACTER SET [=] charset_name| COLLATE [=] collation_name| ENCRYPTION [=] {'y' | 'n'}
}
CHARACTER SET
:指定数据库采用的字符集编码COLLATE
:指定数据库字符集的校验规则ENCRYPTION
:数据库是否加密,MySQL 8.0.16中引⼊的新选项
示例
-- 创建一个名为instance_db1 的数据库
create database instance_db1;-- 自定义一个数据库instance_db2,如果数据库不存在则创建并指定字符集和校验规则
create database if not exists instance_db2 character set utf8mb4 collate utf8mb4_0900_ai_ci;
4. 修改数据库
对数据库的修改主要是修改数据库的字符集,校验规则
语法
ALTER {DATABASE | SCHEMA} [db_name]alter_option ...alter_option: {[DEFAULT] CHARACTER SET [=] charset_name| [DEFAULT] COLLATE SET [=] collation_name| [DEFAULT] ENCRYPTION SET [=] {'Y' | 'N'}| READ ONLY [=] { DEFAULT | 0 | 1 }
}
示例
-- 将instance_db1数据库的字符集改为GBK
alter database instance_db1 character set gbk;
5. 删除数据库
语法
DROP { DATABASE | SCHEMA } [IF EXISTS] 数据库名;
示例
-- 删除掉instance_db2这个数据库
drop database if exists instance_db2;
表的操作
1. 查看所有表
语法
SHOW tables;
示例
-- 查看表
show tables;
2. 创建表
语法
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] 表名(field datatype [约束] [comment '注解内容' ][,field datatype [约束] [comment '注解内容' ]][, ......]
) [engine 存储引擎] [character set 字符集] [collate 排序规则];
TEMPORARY
:表示创建的是⼀个临时表field
:列名datatype
:数据类型comment
:对列的描述或说明engine
:存储引擎,不指定则使用默认存储引擎character set
:字符集,不指定则使用默认字符集collate
:排序规则,不指定则使用默认排序规则
示例
-- 创建一个用户表,表中包含用户id,用户名,密码 并指定字符集为utf8mb4,排序规则为utf8mb4_0900_ai_ci
create table if not exists users (id bigint,name varchar(20) comment '用户名',password char(32) comment '密码是32位的MD5值'
) character set utf8mb4 collate = utf8mb4_0900_ai_ci;
3. 查看表结构
语法
desc 表名;
示例
-- 查看users表的表结构
desc users;
Field
:表中的列名Type
:列的数据类型Null
:该列的值是否允许为NullKey
:该列的索引类型Default
:该列的默认值Extra
:扩展信息
4. 修改表
语法
ALTER TABLE tbl_name [alter_option [, alter_option] ...]; alter_option: {table_options | ADD [COLUMN] col_name column_definition [FIRST | AFTER col_name] | MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name] | DROP [COLUMN] col_name | RENAME COLUMN old_col_name TO new_col_name | RENAME [TO | AS] new_tbl_name
}
tbl_name
:要修改的表名ADD
:向表中添加列MODIFY
:修改表中现有的列DROP
:删除表中现有的列RENAME COLUMN
:重命名表中现有的列RENAME [TO | AS] new_tbl_name
:重命名当前的表
示例
-- 向用户表中添加一列
alter table users ADD assets varchar(100) comment '头像地址' after password;-- 修改用户表中某列长度
alter table users MODIFY assets varchar(255);-- 重命名用户表中某一列
alter table users RENAME COLUMN assets TO avatar_address;-- 删除用户表中某个字段
alter table users DROP avatar_address;-- 修改用户表的表名
alter table users RENAME TO client;
5. 删除表
语法
DROP [TEMPORARY] TABLE [IF EXISTS] 表名 [,表名,...];
TEMPORARY
:表示临时表
示例
-- 删除client表
drop table if exists client;
CRUD
Create 新增
语法
INSERT [INTO] 表名 [(column [,column,...])] VALUES (value_list) [,value_list,...];value_list: value [,value,...]-- 插入查询结果
INSERT INTO 表名 [(列名 [, 列名, ...])] SELECT ...;
示例
-- 创建一个演示的表
create table users (id bigint,name varchar(20) comment '用户名'
);-- 单行数据全列插入,省略插入列列名不写代表全列插入
insert into users values(1,'张三');-- 单行数据指定列插入,value_list中值的数量和顺序必须和指定列匹配
insert into users(id,name) values (2,'李四');-- 多行数据指定列插入
insert into user(id,name) values(3,'王五'),(3,'赵六');-- 创建一张新表结构和exam相同,插入指定查询条件的原exam中的数据
mysql> create table exam_copy like exam;
Query OK, 0 rows affected (0.04 sec)mysql> insert into exam_copy select * from exam where math > 90;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> select * from exam;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 3 | 猪悟能 | 88 | 98 | 90 |
| 4 | 白龙马 | 82 | 84 | 67 |
| 5 | 牛魔王 | 55 | 85 | 45 |
| 6 | 哪吒 | 70 | 73 | 78 |
| 7 | 红孩儿 | 75 | 65 | 30 |
+------+--------+---------+------+---------+
6 rows in set (0.00 sec)mysql> select * from exam_copy;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 3 | 猪悟能 | 88 | 98 | 90 |
+------+--------+---------+------+---------+
2 rows in set (0.00 sec)
Retrieve 检索
语法
SELECT[DISTINCT]查询的列 [,查询的列,...][FROM 查询的表][WHERE 过滤条件][GROUP BY {col_name [,col_name,...]}][HAVING 分组后对分组的过滤条件][ORDER BY {col_name [ASC | DESC ] [,col_name [ASC | DESC ],...]}][LIMIT { [offset,] row_count | row_count OFFSET offset }];
示例
-- 创建一个示例表
mysql> CREATE TABLE exam (-> id BIGINT,-> name VARCHAR(20) COMMENT '同学姓名',-> chinese float COMMENT '语⽂成绩',-> math float COMMENT '数学成绩',-> english float COMMENT '英语成绩'-> );
Query OK, 0 rows affected (0.03 sec)-- 插入测试数据
mysql> INSERT INTO exam (id,name, chinese, math, english) VALUES-> (1, '唐三藏', 67, 98, 56),-> (2, '孙悟空', 87, 78, 77),-> (3, '猪悟能', 88, 98, 90),-> (4, '白龙马', 82, 84, 67),-> (5, '牛魔王', 55, 85, 45),-> (6, '哪吒', 70, 73, 78),-> (7, '红孩儿', 75, 65, 30);
Query OK, 7 rows affected (0.01 sec)
Records: 7 Duplicates: 0 Warnings: 0
1.查询语句示例
-- 全列查询
mysql> select * from exam;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 2 | 孙悟空 | 87 | 78 | 77 |
| 3 | 猪悟能 | 88 | 98 | 90 |
| 4 | 白龙马 | 82 | 84 | 67 |
| 5 | 牛魔王 | 55 | 85 | 45 |
| 6 | 哪吒 | 70 | 73 | 78 |
| 7 | 红孩儿 | 75 | 65 | 30 |
+------+--------+---------+------+---------+
7 rows in set (0.00 sec)-- 指定列查询 (查询所有人的编号,姓名和数学成绩)
mysql> select id, name, math from exam;
+------+--------+------+
| id | name | math |
+------+--------+------+
| 1 | 唐三藏 | 98 |
| 2 | 孙悟空 | 78 |
| 3 | 猪悟能 | 98 |
| 4 | 白龙马 | 84 |
| 5 | 牛魔王 | 85 |
| 6 | 哪吒 | 73 |
| 7 | 红孩儿 | 65 |
+------+--------+------+
7 rows in set (0.00 sec)-- 查询字段为表达式
# 表达式为一个常量
mysql> select id, name, '这是一个常量表达式' from exam;
+------+--------+--------------------+
| id | name | 这是一个常量表达式 |
+------+--------+--------------------+
| 1 | 唐三藏 | 这是一个常量表达式 |
| 2 | 孙悟空 | 这是一个常量表达式 |
| 3 | 猪悟能 | 这是一个常量表达式 |
| 4 | 白龙马 | 这是一个常量表达式 |
| 5 | 牛魔王 | 这是一个常量表达式 |
| 6 | 哪吒 | 这是一个常量表达式 |
| 7 | 红孩儿 | 这是一个常量表达式 |
+------+--------+--------------------+
7 rows in set (0.00 sec)# 表达式中包含一个字段
mysql> select id, name, chinese + 10 from exam;
+------+--------+--------------+
| id | name | chinese + 10 |
+------+--------+--------------+
| 1 | 唐三藏 | 77 |
| 2 | 孙悟空 | 97 |
| 3 | 猪悟能 | 98 |
| 4 | 白龙马 | 92 |
| 5 | 牛魔王 | 65 |
| 6 | 哪吒 | 80 |
| 7 | 红孩儿 | 85 |
+------+--------+--------------+
7 rows in set (0.00 sec)# 表达式中包含多个字段
mysql> select id, name, chinese + math + english from exam;
+------+--------+--------------------------+
| id | name | chinese + math + english |
+------+--------+--------------------------+
| 1 | 唐三藏 | 221 |
| 2 | 孙悟空 | 242 |
| 3 | 猪悟能 | 276 |
| 4 | 白龙马 | 233 |
| 5 | 牛魔王 | 185 |
| 6 | 哪吒 | 221 |
| 7 | 红孩儿 | 170 |
+------+--------+--------------------------+
7 rows in set (0.00 sec)
2.为查询结果指定别名的查询
-- 语法
SELECT column [AS] alias_name [, ...] FROM table_name;-- 为chinese + math + english 指定别名总分
mysql> select id, name, chinese + math + english as '总分' from exam;
+------+--------+------+
| id | name | 总分 |
+------+--------+------+
| 1 | 唐三藏 | 221 |
| 2 | 孙悟空 | 242 |
| 3 | 猪悟能 | 276 |
| 4 | 白龙马 | 233 |
| 5 | 牛魔王 | 185 |
| 6 | 哪吒 | 221 |
| 7 | 红孩儿 | 170 |
+------+--------+------+
7 rows in set (0.00 sec)
3.结果去重查询
使用DISCTINCT
去重时,只有查询列表中所有列的值都相同才会判定为重复
-- 去重前:
mysql> select math from exam;
+------+
| math |
+------+
| 98 |
| 78 |
| 98 |
| 84 |
| 85 |
| 73 |
| 65 |
+------+-- 去重后:
mysql> select distinct math from exam;
+------+
| math |
+------+
| 98 |
| 78 |
| 84 |
| 85 |
| 73 |
| 65 |
+------+
6 rows in set (0.00 sec)
4.Where 条件查询
-- 语法
SELECT select_expr [, select_expr] ... [FROM table_references] WHERE where_condition;
5.Order by 排序
-- 语法
-- ASC 为升序(从⼩到⼤)
-- DESC 为降序(从⼤到⼩)
-- 默认为 ASC
SELECT ... FROM table_name [WHERE ...] ORDER BY {col_name | expr } [ASC | DESC], ...-- 按数学成绩从低到高排序(升序)
mysql> select name, math from exam order by math asc;
+--------+------+
| name | math |
+--------+------+
| 红孩儿 | 65 |
| 哪吒 | 73 |
| 孙悟空 | 78 |
| 白龙马 | 84 |
| 牛魔王 | 85 |
| 唐三藏 | 98 |
| 猪悟能 | 98 |
+--------+------+
7 rows in set (0.00 sec)-- 按语文成绩从高到低排序(降序)
mysql> select name, chinese from exam order by chinese desc;
+--------+---------+
| name | chinese |
+--------+---------+
| 猪悟能 | 88 |
| 孙悟空 | 87 |
| 白龙马 | 82 |
| 红孩儿 | 75 |
| 哪吒 | 70 |
| 唐三藏 | 67 |
| 牛魔王 | 55 |
+--------+---------+
7 rows in set (0.00 sec)-- 查询同学各⻔成绩,依次按数学降序,英语升序,语⽂升序的⽅式显⽰
mysql> select name, math, english, chinese from exam order by math desc,-> english asc, chinese asc;
+--------+------+---------+---------+
| name | math | english | chinese |
+--------+------+---------+---------+
| 唐三藏 | 98 | 56 | 67 |
| 猪悟能 | 98 | 90 | 88 |
| 牛魔王 | 85 | 45 | 55 |
| 白龙马 | 84 | 67 | 82 |
| 孙悟空 | 78 | 77 | 87 |
| 哪吒 | 73 | 78 | 70 |
| 红孩儿 | 65 | 30 | 75 |
+--------+------+---------+---------+
7 rows in set (0.00 sec)
6.分页查询
-- 语法
-- 起始下标为 0
-- 从 0 开始,筛选 num 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT num;
-- 从 start 开始,筛选 num 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT start, num;
-- 从 start 开始,筛选 num 条结果,⽐第⼆种⽤法更明确,建议使⽤
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT num OFFSET start-- 示例
mysql> select * from exam order by id asc limit 0, 3;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 2 | 孙悟空 | 87 | 78 | 77 |
| 3 | 猪悟能 | 88 | 98 | 90 |
+------+--------+---------+------+---------+
3 rows in set (0.00 sec)mysql> select * from exam order by id asc limit 3;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 2 | 孙悟空 | 87 | 78 | 77 |
| 3 | 猪悟能 | 88 | 98 | 90 |
+------+--------+---------+------+---------+
3 rows in set (0.00 sec)mysql> select * from exam order by id asc limit 3 offset 0;
+------+--------+---------+------+---------+
| id | name | chinese | math | english |
+------+--------+---------+------+---------+
| 1 | 唐三藏 | 67 | 98 | 56 |
| 2 | 孙悟空 | 87 | 78 | 77 |
| 3 | 猪悟能 | 88 | 98 | 90 |
+------+--------+---------+------+---------+
3 rows in set (0.00 sec)
7.GROUP BY 分组查询
SELECT
中使用GROUP BY子句
可以对指定列进行分组查询,需要满足:
使用GROUP BY子句
进行分组查询时,SELECT
指定的字段必须是分组依据字段
,其他字段要想出现在SELECT
中必须包含在聚合函数中。
常用的聚合函数:
-- 语法
SELECT col1 ,聚合函数 (col2),... FROM 表名 GROUP BY col1 [,...,], ... [HAVING 针对分组后的过滤条件];-- 示例-- 创建一张测试表并初始化
mysql> create table emp (-> id bigint primary key auto_increment,-> name varchar(20) not null,-> role varchar(20) not null,-> salary decimal(10, 2) not null-> );
Query OK, 0 rows affected (0.03 sec)mysql> insert into emp values (1, '马云', '老板', 1500000.00);
Query OK, 1 row affected (0.01 sec)mysql> insert into emp values (2, '马化腾', '老板', 1500000.00);
Query OK, 1 row affected (0.01 sec)mysql> insert into emp values (3, '孙悟空', '游戏角色', 956.8);
Query OK, 1 row affected (0.01 sec)mysql> insert into emp values (4, '猪八戒', '游戏角色', 700.5);
Query OK, 1 row affected (0.01 sec)mysql> insert into emp values (5, '沙悟净', '游戏角色', 333.3);
Query OK, 1 row affected (0.01 sec)mysql> select * from emp;
+----+--------+----------+------------+
| id | name | role | salary |
+----+--------+----------+------------+
| 1 | 马云 | 老板 | 1500000.00 |
| 2 | 马化腾 | 老板 | 1500000.00 |
| 3 | 孙悟空 | 游戏角色 | 956.80 |
| 4 | 猪八戒 | 游戏角色 | 700.50 |
| 5 | 沙悟净 | 游戏角色 | 333.30 |
+----+--------+----------+------------+
5 rows in set (0.00 sec)-- 统计每个角色的平均工资
mysql> select role,ROUND(avg(salary),2) as '平均工资' from emp group by role;
+----------+------------+
| role | 平均工资 |
+----------+------------+
| 老板 | 1500000.00 |
| 游戏角色 | 663.53 |
+----------+------------+
2 rows in set (0.00 sec)
Having 子句
使用GROUP BY
对结果进行分组处理之后,对分组的结果进行过滤时,不能使用 WHERE ⼦句
,而要使用 HAVING ⼦句
-- 显⽰平均⼯资低于1500的⻆⾊和它的平均⼯资
mysql> select role, avg(salary) from emp group by role having avg(salary) < 1500;
+----------+-------------+
| role | avg(salary) |
+----------+-------------+
| 游戏角色 | 663.533333 |
+----------+-------------+
1 row in set (0.00 sec)
Update 修改
语法
UPDATE [LOW_PRIORITY] [IGNORE] 表名 SET 列名 [, 列名,...] [WHERE 过滤条件] [ORDER BY ...] [LIMIT row_count];
示例
-- 将孙悟空的数学成绩变更为80分
mysql> update exam set math = 80 where name = '孙悟空';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Delete 删除
语法
DELETE FROM 表名 [WHERE 过滤条件] [ORDER BY ...] [LIMIT row_count];
示例
mysql> delete from exam where name = '孙悟空';
Query OK, 1 row affected (0.01 sec)
联合查询
联合多个表进行查询的查询就叫联合查询。
内连接
-- 语法-- 写法(1)
select 字段 from 表1 别名1, 表2 别名2 where 连接条件 and 其他条件;-- 写法(2)
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
外连接
-- 表名也可以起别名
-- 左外连接,表1完全显⽰
select 字段名 from 表名1 left join 表名2 on 连接条件;-- 右外连接,表2完全显⽰
select 字段 from 表名1 right join 表名2 on 连接条件;
自连接
-- 自连接是连接同一张表,这时需要取不同的别名 否则无法识别唯一的表
select * from 表名 别名1, 表名 别名2 [where 过滤条件] [...];
子查询
子查询是把⼀个SELECT语句
的结果当做另外⼀个SELECT语句的条件,也叫嵌套查询
-- 语法
select * from 表名1 where col_name1 { = | IN } ( select col_name1 from 表名2 where col_name2 {= | IN} [( select ...) ] ... );-- 示例
mysql> select * from emp where id in (select id from emp where role = '老板');
+----+--------+------+------------+
| id | name | role | salary |
+----+--------+------+------------+
| 1 | 马云 | 老板 | 1500000.00 |
| 2 | 马化腾 | 老板 | 1500000.00 |
+----+--------+------+------------+
2 rows in set (0.00 sec)
在from 子句中使用子查询
当⼀个查询产生结果时,MySQL⾃动创建⼀个临时表,然后把结果集放在这个临时表中,最终返回给用户,在from⼦句中也可以使用临时表进行子查询或表连接操作。
合并查询
合并多个查询结果的结果集,使用union 或 union all 来连接查询结果
-- 语法
select * from 表1 union select * from 表2;select * from 表1 union all select * from 表2;
当使用UNION
时,会自动去掉结果集中的重复行,而UNION ALL
则不会。
数据库约束
- 约束类型
CREATE TABLE Employees (emp_id BIGINT AUTO_INCREMENT,name VARCHAR(100) NOT NULL, -- 非空约束email VARCHAR(100) UNIQUE, -- 唯一约束hire_date DATE NOT NULL DEFAULT CURRENT_DATE, -- 默认值约束department_id INT NOT NULL, -- 非空约束PRIMARY KEY (emp_id), -- 主键约束FOREIGN KEY (department_id) REFERENCES Departments(department_id) -- 外键约束
);
emp_id
列是主键(PRIMARY KEY
),它保证了每个员工的唯一性,并且隐式地被NOT NULL
。name
列使用了NOT NULL
约束,确保员工必须有名字。email
列使用了UNIQUE
约束,确保每个员工的电子邮件地址是唯一的。hire_date
列使用了NOT NULL
和DEFAULT
约束,确保每个员工都有入职日期,并且默认值是当前日期。department_id
列使用了NOT NULL
约束,确保每个员工必须指定一个部门。department_id
列的外键约束(FOREIGN KEY
)确保员工所指定的部门存在于Departments
表中。