Mysql笔记01-安装和SQL基础
1.Docker安装Mysql
容器的启动
#拉取镜像(不添加版本,默认latest)
docker pull mysql
cd /home/admin/mysql
docker run -p 3306:3306 --name mysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql
命令解释:
-p 3306:3306 将主机的3306端口映射到容器内部的3306端口
--name mysql 指定运行的容器名为mysql
-v $PWD/conf:/etc/mysql/conf.d 将容器内部的配置目录/etc/mysql/conf.d挂载到主机目录$PWD/conf
-v $PWD/logs:/logs 将容器内部的日志目录/logs挂载到主机目录$PWD/logs
-v $PWD/data:/var/lib/mysql 将容器内部的数据目录/var/lib/mysql挂载到主机目录$PWD/data
-e MYSQL_ROOT_PASSWORD=123456 设置数据库root用户的密码为123456
-d 设置容器在后台运行
权限的控制
新创建的容器默认root权限只有本机登录,即只能在容器内使用,需要更改权限。
use mysql;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
2.SQL基础
2.1SQL简介
SQL是Structure Query Language(结构化查询语句)的缩写,它是使用关系模型的数据库应用语言。
2.2SQL分类
SQL语句主要可以划分为以下3个类别。
- DDL(Data Definition Languages)语句:数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象。常用的语句关键字主要包括create、drop、alter等。
- DML(Data Manipulation Languages)语句:数据操纵语句,用于添加、删除、更新和查询数据记录,并检查数据完整性。常用的语句关键字主要包括insert、delete、update和select等。
- DCL(Data Control Languages)数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括grant、revoke等。
2.2.1DDL语句
DDL是数据定义语言的缩写,简单说就是对数据库内部的对象进行创建、删除、修改等操作语句。DDL语句更多由数据库管理员(DBA)使用,开发人员一半很少使用。
1.连接数据库
[root@izuf68l8jiwy7fo0zpek0bz ~]# mysql -h127.0.0.1 -uroot -p
Enter password:
在以上命令中,mysql代表客户端的命令,-p表述数据库的地址,-u后面连接的数据库用户名称,-p表示要输入密码。(使用-h代表使用了TCP/IP套接字方式连接,如果不使用表示使用Unix域套接字连接)
拓展补充:https://www.cnblogs.com/wade-luffy/p/6274895.html
2.创建数据库
语法如下:
CREATE DATABASE dbname
mysql> create database test1;
Query OK, 1 row affected (0.01 sec)
其中提示的“Query OK, 1 row affected (0.01 sec)”,这段提示可以分为3部分。
- ”Query OK“表示上面的命令执行成功,Mysql的特点是所有的DDL和DML操作执行成功后都显示"Query OK",可以理解成执行成功。
- "1 row affected" 表示操作只影响了数据库中的一行的记录
- "0.01 sec"则记录了操作执行的时间。
删除数据库
语法如下:
DROP DATABASE dbname
创建表
语法如下:
CREATE TABLE tablename (
column_name_1 column_type_1 constraints,
column_name_2 column_type_2 constraints,
...
column_name_n column_type_n constraints)
column_name 是列的名字;
column_type 是列的数据类型;
Constraints 是这个列的约束条件
举个栗子:
mysql> CREATE TABLE emp(ename varchar(10),hiredate date,sal decimal(10.2),deptno int(2));
Query OK, 0 rows affected, 1 warning (0.02 sec)
查看表的定义如下:
mysql> desc emp;
+----------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| ename | varchar(10) | YES | | NULL | |
| hiredate | date | YES | | NULL | |
| sal | decimal(10,0) | YES | | NULL | |
| deptno | int | YES | | NULL | |
+----------+---------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> show create table emp \G;
*************************** 1. row ***************************
Table: emp
Create Table: CREATE TABLE `emp` (
`ename` varchar(10) DEFAULT NULL,
`hiredate` date DEFAULT NULL,
`sal` decimal(10,0) DEFAULT NULL,
`deptno` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.01 sec)
ERROR:
No query specified
注:"\G"选项的含义是使得记录能够按照字段竖向排序,已变更好地展示内容较长的记录。
修改表
语法如下:
ALTER TABLE tablename MODIFY [COLUMN] column_definition[FIRST|AFTER col_name]
举个栗子:
--增加表字段age
alter table emp add column age int(3);
--删除表字段age
alter table emp drop column age;
--字段改名ename
alter table emp change ename vname varchar(20);
--新增字段,添加在ename之后
alter table emp add id int(10) after vname;
--修改某字段的位置
alter table emp modify id int first;
修改表名:
语法如下:
ALTER TABLE tablename RENAME [TO] new_tablename
alter table emp rename emp1;
2.2.2DML语句
DML操作是指对数据库中表记录的操作,主要包括表记录的插入(insert)、更新(update)、删除(delete)和查询(select),是开发人员日常使用最频繁的操作。
1.插入记录
语法格式:
INSERT INTO tablename (field1, field2,...fieldn) VALUES(value1,value2,...valuen);
INSERT INTO tablename VALUES(value1,value2,...valuen)
可以不用指定字段名称,但是values后面的顺序应该和字段的排列顺序一致。
insert into emp (ename,sal,deptno) values ('zhangsan',2222,333);
insert into emp values('jiangfeng','2021-06-17',2,2);
2. 更新记录
语法格式:
UPDATE tablename SET field1=value1,field2=value2,...[WHERE CONDITION]
例子:
update emp SET hiredate='2020-01-01' where sal=2222;
删除记录
语法格式:
DELETE FROM tablename [WHERE CONDITION]
查询记录
数据插入到数据库中后,就可以用SELECT命令进行各种各样的查询,使得输出的结果符合用户的要求。
语法格式:
SELECT[ALL|DISTINCT|DISTINCTROW|TOP]
{|talbe.|[table.]field1[AS alias1][,[table.]field2[AS alias2][,…]]}
FROM tableexpression[,…][IN externaldatabase]
[WHERE…]
[GROUP BY…]
[HAVING…]
[ORDER BY…]
(0)最简单的查询
查询最简单的方式是将记录全部取出。其中'*'表示要将所有的记录都选出来,也可以用逗号分隔的所有字符串来代替。
mysql> select * from emp;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| zhangsan | 2020-01-01 | 2222 | 333 |
+-----------+------------+------+--------+
2 rows in set (0.00 sec)
(1)查询不重复的记录
有时需要将表中的记录去掉重复后显示出来,可以使用distinct关键字来实现。
mysql> select * from emp;;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| zhangsan | 2020-01-01 | 2222 | 333 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | NULL | 333 | 444 |
| zhangsan | NULL | 333 | 444 |
+-----------+------------+------+--------+
5 rows in set (0.00 sec)
ERROR:
No query specified
mysql> select distinct * from emp;;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| zhangsan | 2020-01-01 | 2222 | 333 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | NULL | 333 | 444 |
+-----------+------------+------+--------+
4 rows in set (0.00 sec)
mysql> select distinct ename from emp;
+-----------+
| ename |
+-----------+
| jiangfeng |
| zhangsan |
+-----------+
2 rows in set (0.01 sec)
(2)条件查询
在很多情况下,用户并不需要查询所有的记录,而只是需要根据限定条件来查询一部分数据,用where关键字可以实现这样的操作。
mysql> select * from emp where ename='jiangfeng';
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| jiangfeng | NULL | 333 | 444 |
+-----------+------------+------+--------+
2 rows in set (0.00 sec)
上面的例子中,where后面的条件时一个字段的'='比较,除了'='外,还可以使用>、<、>=、<=、!= 等比较运算符;多个条件之间还可以使用or、and等逻辑运算符进行多条件联合查询。
mysql> select * from emp where ename='jiangfeng' and sal >100;
+-----------+----------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+----------+------+--------+
| jiangfeng | NULL | 333 | 444 |
+-----------+----------+------+--------+
1 row in set (0.00 sec)
(3)排序
关键字:ORDER BY
例子:
mysql> select * from emp order by sal;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | NULL | 333 | 444 |
| zhangsan | NULL | 333 | 444 |
| zhangsan | 2020-01-01 | 2222 | 333 |
+-----------+------------+------+--------+
5 rows in set (0.00 sec)
mysql> select * from emp order by sal desc;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| zhangsan | 2020-01-01 | 2222 | 333 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | NULL | 333 | 444 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | 2021-06-17 | 2 | 2 |
+-----------+------------+------+--------+
5 rows in set (0.00 sec)
其中DESC和ASC是排序顺序关键字,DESC表示按照字段进行降序排序,ASC表示升序,如果不写默认升序。
ORDER BY 后面可以跟多个不同的排序字段,如果排序字段的值一样,则按照第二个排序字段进行排序,以此类推。如果只有一个排序字段,则这些字段相同的记录将会无序排序。
(4)限制
如果只希望显示一部分,而不是全部,可以用关键字LIMIT来实现。LIMIT的语法如下:
SELECT ...[LIMIT offset_start,row_count]
其中offset_start表示记录的偏移量,row_count表示显示的行数。
默认情况下,起始偏移量为0,只需要写记录行数就可以。
举例:
mysql> select * from emp limit 3;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| zhangsan | 2020-01-01 | 2222 | 333 |
| zhangsan | NULL | 333 | 444 |
+-----------+------------+------+--------+
3 rows in set (0.00 sec)
mysql> select * from emp limit 1,3;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| zhangsan | 2020-01-01 | 2222 | 333 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | NULL | 333 | 444 |
+-----------+------------+------+--------+
3 rows in set (0.00 sec)
(5)聚合
一般情况下,用户都需要进行一些汇总操作,比如统计人数等,这时就要用到SQL的聚合操作。语法如下:
SELECT [field1,field2,....] func_name
FROM tablename
[WHERE where_contition]
[GROUP BY field1,field2,...]
[WHTH ROLLUP]
[HAVING where_contition]
对其参数进行以下说明:
- func_name 表示要做的聚合操作,也就是聚合函数,常用的有sum\count\max\min.
- GROUP BY关键字表示要进行分类聚合的字段,比如要按照部门分类统计员工数量,部门就应该写在group by后面。
- WITH ROLLUP时可选语法,表明是否对分类聚合后的结果进行再汇总。
- HAVING 关键字表示对分类后的结果再进行条件的过滤。
注意:having和where的区别在于,having是对聚合后的结果进行条件的过滤,而where是在聚合前就对记录进行过滤。如果逻辑允许,尽可能用where先过滤记录,这样因为结果集减少,将对聚合的效率大大提高,最后再根据逻辑看是否用having进行再过滤。
mysql> select deptno,count(1) from emp group by deptno;
+--------+----------+
| deptno | count(1) |
+--------+----------+
| 2 | 1 |
| 333 | 1 |
| 444 | 3 |
+--------+----------+
3 rows in set (0.00 sec)
mysql> select deptno,count(1) from emp where ename='jiangfeng' group by deptno;
+--------+----------+
| deptno | count(1) |
+--------+----------+
| 2 | 1 |
| 444 | 1 |
+--------+----------+
2 rows in set (0.00 sec)
(6)表连接
当需要同时显示多个表中的字段时,就可以使用表连接来实现这样的功能。从大类上分,表连接分为内连接和外连接。
他们之间的最主要区别是,内连接仅选出两张表中互相匹配的记录,而外连接会选出其他不匹配的记录。
内连接例子:
mysql> select * from emp;
+-----------+------------+------+--------+
| ename | hiredate | sal | deptno |
+-----------+------------+------+--------+
| jiangfeng | 2021-06-17 | 2 | 2 |
| zhangsan | 2020-01-01 | 2222 | 333 |
| zhangsan | NULL | 333 | 444 |
| jiangfeng | NULL | 333 | 444 |
| zhangsan | NULL | 333 | 444 |
+-----------+------------+------+--------+
5 rows in set (0.00 sec)
mysql> select * from emp1;
+--------+------------+------+--------+
| ename | hiredate | sal | deptno |
+--------+------------+------+--------+
| zzz | 2020-01-01 | 2000 | 1 |
| lisa | 2003-02-01 | 4000 | 2 |
| bjguan | 2004-04-01 | 5000 | 1 |
| bzshen | 2005-04-01 | 4000 | 3 |
+--------+------------+------+--------+
4 rows in set (0.00 sec)
mysql> select * from dept;
+--------+----------+
| deptno | deptname |
+--------+----------+
| 1 | tech |
| 2 | sale |
| 3 | hr |
+--------+----------+
3 rows in set (0.00 sec)
mysql> select ename,deptname from emp1,dept where emp1.deptno=dept.deptno;
+--------+----------+
| ename | deptname |
+--------+----------+
| zzz | tech |
| lisa | sale |
| bjguan | tech |
| bzshen | hr |
+--------+----------+
4 rows in set (0.00 sec)
mysql> select ename,deptname from emp,dept where emp.deptno=dept.deptno;
+-----------+----------+
| ename | deptname |
+-----------+----------+
| jiangfeng | sale |
+-----------+----------+
1 row in set (0.00 sec)
外连接又分为左连接和又连接,具体定义如下:
- 左连接:包含所有的左边表中的记录甚至右边表中没有和他匹配的记录。
- 右连接:包含所有的又边表中的记录甚至右边表中没有和他匹配的记录。
mysql> select ename,deptname from emp left join dept on emp.deptno=dept.deptno;
+-----------+----------+
| ename | deptname |
+-----------+----------+
| jiangfeng | sale |
| zhangsan | NULL |
| zhangsan | NULL |
| jiangfeng | NULL |
| zhangsan | NULL |
+-----------+----------+
5 rows in set (0.00 sec)
(7)子查询
某些情况下,当进行查询时,需要的条件是另外一个select语句的结果,这个时候,就要用到子查询。用于子查询的关键字主要包括in、not in、=、!=、exists、no t exists等。
mysql> select * from emp1 where deptno in(select deptno from dept);
+--------+------------+------+--------+
| ename | hiredate | sal | deptno |
+--------+------------+------+--------+
| zzz | 2020-01-01 | 2000 | 1 |
| lisa | 2003-02-01 | 4000 | 2 |
| bjguan | 2004-04-01 | 5000 | 1 |
| bzshen | 2005-04-01 | 4000 | 3 |
+--------+------------+------+--------+
4 rows in set (0.01 sec)