# MySQL

MySQL 是最流行的关系型数据库管理系统,那么什么是数据库呢?

# MySQL vs SQLite

MySQL和SQLite是两种不同类型的数据库管理系统(DBMS),在一些方面有所不同:

  1. 性能:MySQL是一个客户端/服务器模型的DBMS,它需要一个专门的服务器进程来处理客户端请求。相比之下,SQLite是一个嵌入式的DBMS,它不需要网络通信和服务器进程,所有的数据操作都是在应用程序进程中进行的。因此,SQLite通常比MySQL更快,特别是在单用户、低并发的情况下。
  2. 功能:MySQL是一个功能非常丰富的DBMS,支持多种存储引擎、复制、集群、分区、备份、恢复等高级功能。而SQLite则相对简单,不支持分布式、高可用性、复制等高级功能。但是,SQLite支持标准的SQL语言、事务、触发器、视图等基本功能,足以满足许多应用程序的需求。
  3. 并发性:MySQL支持更高级别的事务隔离级别,如可重复读和串行化。而SQLite只支持较低的事务隔离级别,如读已提交和可重复读。因此,在高并发的多用户环境下,MySQL更适合处理大量的并发事务。
  4. 部署:MySQL通常部署在一个独立的服务器上,需要一个专门的管理员来管理和维护。而SQLite则直接嵌入到应用程序中,不需要额外的管理和维护,因此更容易部署和使用。

综上所述,MySQL和SQLite都有其独特的优缺点,应该根据具体的应用场景和需求来选择适合的DBMS。如果需要处理大量的并发事务、需要高可用性和复制等高级功能,那么MySQL是更好的选择;如果需要一个简单、轻量级的DBMS,或者需要在移动设备和桌面应用程序中使用,那么SQLite是更好的选择。

# MySQL 安装

apt 安装

# 安装服务
apt isntall mysql-server
# 启动服务
service mysqld start
# 停止服务
service mysqld stop
# 查看服务状态
service mysqld status

docker 安装

docker run -itd \
--restart always \
--name mysql-dev \
-p 3307:3306 \
-v /docker/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql

windows

使用这个安装 https://dev.mysql.com/downloads/mysql/ (opens new window)

mysqladmin --version

# 配置

# 步骤一:生成临时密码
grep 'temporary password' /var/log/mysqld.log

# 步骤二:使用临时密码登陆
mysql -uroot -p

# 步骤三:更改密码
ALTER USER 'root'@'localhost' IDENTIFIED BY '$oK123456!';

# 步骤四:退出并用新密码登陆
exit
  • 登录 MySQL

mysql -h 主机名 -u 用户名 -p
mysql -u 用户名 -p
mysql -u 用户名

参数说明:

  • h : 指定客户端所要登录的 MySQL 主机名, 登录本机(localhost 或 127.0.0.1)该参数可以省略;

  • u : 登录的用户名;

  • p : 告诉服务器将会使用一个密码来登录, 如果所要登录的用户名密码为空, 可以忽略此选项。

  • 修改密码


mysqladmin -u root password "new_password";
  • 设置远程登录

#找到bind-address所在行 45
# Instead of skip-networking the default is now to listen only on 46
# localhost which is more compatible and is not less secure. 47
bind-address        = 127.0.0.1
# 将 bind-address值修改为本机IP即可。
#注意注释说明,如果是较老版本的MySQL,此处就应该是skip-networking,直接将其注释即可。

# 内部操作

  • 创建数据库 create database
mysql> create database <database_name>;
mysql> create database <database_name> charset utf8;
mysql> show create database <database_name>;
  • 删除数据库 drop database
mysql> drop database <database_name>;
mysql> drop database if exists <database_name>;

# 外部操作

  • 备份数据库(导出)mysqldump

mysqldump [参数]  –h 主机地址  –u 登录名 –p 数据库名 > 文件.sql
mysql -h localhost -u login -p database_name > database_back.sql
  • 恢复数据库(导入)source

mysql –u 登录名 –p 数据库名 < 文件名.sql
mysql -u login_name -p database_name < database_back.sql
mysql> source  文件名.sql

# MySQL 创建表

# 创建表

-- 创建表
DROP TABLE IF  EXISTS class;
CREATE TABLE class(
	id INT PRIMARY KEY AUTO_INCREMENT,
	cname VARCHAR(30) NOT NULL,
	description VARCHAR(100)
);
-- 查看表结构
DESC class;
SHOW COLUMNS FROM class

# 插入数据项

-- 插入单条数据
INSERT class SET cname = "php" , description = "学习php 开发网站";
-- 插入多条数据
INSERT INTO class (cname, description) 
VALUES 
("linux","服务器知识"),
("mysql","数据库知识");

# 迁移数据到其他表

-- 复制表结构
CREATE TABLE tests LIKE class;
DESC tests;
-- 迁移数据
INSERT INTO test SELECT * FROM class;

# 复制表和表中数据

CREATE TABLE class_bak SELECT * FROM class;
-- 给列取别名
CREATE TABLE class_sub SELECT cname AS name FROM class;

# MySQL 增删改查

# 准备阶段

-- 建表
DROP TABLE IF EXISTS student;
CREATE TABLE student(
  id INT PRIMARY KEY AUTO_INCREMENT,
  sname CHAR(10),
  class_id INT DEFAULT NULL,
  age SMALLINT NOT NULL
);
-- 插入数据
INSERT 
INTO student (sname, class_id, age) 
VALUES
('小赵',1,31),
('小钱',1,22),
('小孙',1,33),
('小李',NULL,34),
('小周',2,21),
('小吴',2,22),
('小郑',2,33),
('小王',2,24);
SELECT * FROM student;

查询结果

    id  sname   class_id     age  
------  ------  --------  --------
     1  小赵             1        33
     2  小钱             1        33
     3  小孙             1        33
     4  小李        (NULL)        33
     5  小周             2        20
     6  小吴             2        20
     7  小郑             2        20
     8  小王             2        20

# 模糊查询

SELECT * FROM student
WHERE class_id=2
OR sname LIKE '%李%';
    id  sname   class_id     age  
------  ------  --------  --------
     4  小李        (NULL)        33
     5  小周             2        20
     6  小吴             2        20
     7  小郑             2        20
     8  小王             2        20

# 范围查询

BETWEEN

-- AND
SELECT * FROM student WHERE age >= 25 AND age <= 40;
-- 等价
SELECT * FROM student WHERE age BETWEEN 25 AND 40;
-- NOT
SELECT * FROM student WHERE age NOT BETWEEN 25 AND 40;

查询结果

    id  sname   class_id     age  
------  ------  --------  --------
     1  小赵             1        33
     2  小钱             1        33
     3  小孙             1        33
     4  小李        (NULL)        33

IN

SELECT * FROM student WHERE class_id IN (2,3);
    id  sname   class_id     age  
------  ------  --------  --------
     5  小周             2        20
     6  小吴             2        20
     7  小郑             2        20
     8  小王             2        20

# 去重

SELECT DISTINCT class_id FROM stu;

# 分页

SELECT * FROM student LIMIT 5;
SELECT * FROM student LIMIT 5 OFFSET 5;

# NULL 处理

NULL 不能和任何值比较

-- 无效,查询无结果
SELECT * FROM student WHERE class_id = NULL;
SELECT * FROM student WHERE class_id IS NULL;

查询结果

    id  sname   class_id     age  
------  ------  --------  --------
     4  小李        (NULL)        33
SELECT sname, IF(class_id, class_id, '未分配') FROM student;
SELECT sname, IFNULL(class_id, '未分配') FROM student;

查询结果

sname   IFNULL(class_id, '未分配')  
------  -------------------------------
小赵      1                              
小钱      1                              
小孙      1                              
小李      未分配                      
小周      2                              
小吴      2                              
小郑      2                              
小王      2                              

# 排序

ORDER BY

SELECT * FROM student  ORDER BY class_id, age ASC;
    id  sname   class_id     age  
------  ------  --------  --------
     2  小钱             1        22
     1  小赵             1        31
     3  小孙             1        33
     5  小周             2        21
     6  小吴             2        22
     8  小王             2        24
     7  小郑             2        33

# 组合使用

SELECT * FROM student 
WHERE 
  class_id = 2 
  AND 
  age IS NOT NULL
ORDER BY  
  age ASC
LIMIT 1;
    id  sname   class_id     age  
------  ------  --------  --------
     5  小周             2        21

# 更新数据

UPDATE student SET class_id = 2 WHERE class_id IS NULL;
SELECT * FROM student;
    id  sname   class_id     age  
------  ------  --------  --------
     1  小赵             1        31
     2  小钱             1        22
     3  小孙             1        33
     4  小李             2        34
     5  小周             2        21
     6  小吴             2        22
     7  小郑             2        33
     8  小王             2        24
-- 把年龄大于 30 的同学分配到 3 班
UPDATE student SET class_id = 3 WHERE age > 30;
SELECT * FROM student ORDER BY age;
    id  sname   class_id     age  
------  ------  --------  --------
     5  小周             2        21
     2  小钱             1        22
     6  小吴             2        22
     8  小王             2        24
     1  小赵             3        31
     3  小孙             3        33
     7  小郑             3        33
     4  小李             3        34
-- 删除最后报名的两个同学
DELETE FROM student ORDER BY id DESC LIMIT 2;
SELECT * FROM student;
    id  sname   class_id     age  
------  ------  --------  --------
     1  小赵             3        31
     2  小钱             1        22
     3  小孙             3        33
     4  小李             3        34
     5  小周             2        21
     6  小吴             2        22

# 添加数据

INSERT INTO student SET sname = '小盾', age = 33, class_id = 3;
INSERT INTO student 
(sname, age, class_id) 
VALUES
('张三', 22, 1),
('李四', 18, NULL);
SELECT * FROM student;
    id  sname   class_id     age  
------  ------  --------  --------
     1  小赵             3        31
     2  小钱             1        22
     3  小孙             3        33
     4  小李             3        34
     5  小周             2        21
     6  小吴             2        22
     9  小盾             3        33
    10  张三             1        22
    11  李四        (NULL)        18

# MySQL 查询

# 准备阶段

DROP TABLE IF  EXISTS class;
CREATE TABLE class(
	id INT PRIMARY KEY AUTO_INCREMENT,
	cname VARCHAR(30) NOT NULL,
	DESCRIPTION VARCHAR(100)
);
DESC class
INSERT INTO class (cname, DESCRIPTION) 
VALUES 
("linux","服务器知识"),
("mysql","数据库知识"),
("php","学习 PHP"),
("java","学习 Java");

# 获取所有行

SELECT *
FROM class;
-- 只需要其中部分的列
SELECT name, id AS ids 
FROM class;

# 条件查询

SELECT *
FROM class
WHERE 
description LIKE '%p%';
SELECT * 
FROM class 
WHERE 
  description LIKE '%p%'
  OR 
  id > 2;

# MySQL LIKE

# 语法

WHERE LIKE ''

# 占位符

  • 下划线 _ 表示一个字符
  • 百分号 % 表示一个或做个字符
语法 作用
LIKE 'a%' 以 a 开头的任意字符
LIKE '%a' 以 a 结尾的任意字符
LIKE '%a%' 包含 a 的任意字符
LIKE 'a%b' 以 a 开头 b 结尾的任意字符
LIKE 'a__%' 以 a 开头 长度至少为 3 的任意字符

# 举例

-- 查找地址是岳麓开头的用户
SeLECT * FROM customers
WHERE address LIKE '岳麓%'
-- 查找地址是小区结尾的用户
SeLECT * FROM customers
WHERE address LIKE '%小区'
-- 查找地址是岳麓开头并且长度至少为 4 的用户
SeLECT * FROM customers
WHERE address LIKE '岳麓__%'

# SQL 速查表

# 查询单个表

SELECT * FROM country;
SELECT id, name FROM city;

# 排序

SELECT name FROM city ORDER BY rating ASC;
SELECT name FROM city ORDER BY rating DESC;

# 别名

SELECT name AS city_name FROM city;
SELECT co.name AS country_name, ci.name AS city_name 
FROM city AS ci
JOIN country AS co ON ci.country_id = co.id;

# 过滤

SELECT name FROM city WHERE rating > 3;

获取名称既不是 Berlin 也不是 Madrid 的城市:

SELECT name FROM city WHERE name NOT IN ('Berlin', 'Madrid');

# 文本操作符

SELECT name FROM city WHERE name LIKE 'P%' OR name LIKE '%s';
SELECT name FROM city WHERE name LIKE 'B%' AND name LIKE '%n';
SELECT name FROM city WHERE name LIKE '_r%' OR name LIKE '%t_';

# 数值操作符

SELECT name FROM city WHERE population BETWEEN 100000 AND 500000;

# 空值检查

SELECT name FROM city WHERE rating IS NULL;
SELECT name FROM city WHERE rating IS NOT NULL;

# 分组和聚合

SELECT country_id, COUNT(*) AS city_count 
FROM city 
GROUP BY country_id;

# 子查询

SELECT name 
FROM city 
WHERE id IN (SELECT city_id FROM airport);

# 连接类型

SELECT co.name AS country_name, ci.name AS city_name 
FROM city AS ci
LEFT JOIN country AS co ON ci.country_id = co.id;
SELECT co.name AS country_name, ci.name AS city_name 
FROM city AS ci
RIGHT JOIN country AS co ON ci.country_id = co.id;

# 联合查询

SELECT name FROM city WHERE rating > 5
UNION
SELECT name FROM airport WHERE capacity > 10000;

# 学习资料

哔哩哔哩 - MYSQL系统课程 (opens new window)