MySQL 自学笔记(入门基础篇,含示例)

目录


一、基础

注意:MySQL语句对大小写不敏感!因此大写或者小写都可以!

1.变量

sql 复制代码
BOOLEAN #bool类型

INT #4bytes整数

FLOAT #4bytes单精度浮点数
DOUBLE #8bytes双精度浮点数
DECIMAL(M,D) #M为总数,D为小数位数

DATE #YYYY-MM-DD
TIME #HH:MM:SS
YEAR #YYYY
DATETIME #YYYY-MM-DD hh:mm:ss,8bytes不依赖时区
TIMESTAMP #YYYY-MM-DD hh:mm:ss,4bytes依赖时区

CHAR #定长字符串
VARCHAR #变长字符串
BLOB #二进制形式的长文本数据

--也可以这样注释

2.运算符

sql 复制代码
# 算数运算符(部分+ - *已省略)
/ 或 DIV	除法
% 或 MOD	取余

# 比较运算符(部分>  <  >=  <=已省略)
=			等于	# 注意不是==
<>, !=		不等于	
BETWEEN		在两值之间	>=min&&<=max
NOT BETWEEN	不在两值之间	
IN			在集合中	
NOT IN		不在集合中	
<=>			严格比较两个NULL值是否相等
LIKE		模糊匹配	
REGEXP		正则式匹配	
RLIKE		正则式匹配	
IS NULL		为空	
IS NOT NULL	不为空

# 逻辑运算符
NOT 或 !	逻辑非
AND			逻辑与
OR			逻辑或
XOR			逻辑异或

二、数据库与表

1.创建数据库

sql 复制代码
CREATE DATABASE sql_tutorial; #创建数据库,sql_tutorial为名称
CREATE DATABASE `sql_tutorial`;  #更加推荐的写法

SHOW DATABASES; #显示已有数据库

USE `sql_tutorial`;#使用该数据库

DROP DATABASE `sql_tutorial`; #删除数据库

2.表的增删与修改

表的组成(列):PRIMARY KEY + VALUES + FOREIGN KEY

其中,
PRIMARY KEY 用于唯一标识对应行数据(类似哈希表的key),可以由多个量组合。
FOREIGN KEY用于链接其他表

(1)表的创建与删除

sql 复制代码
CREATE TABLE `student`( #创建表
    `student_id` INT PRIMARY KEY, #名称 类型 特殊条件,将其指定为PRIMARY KEY
    `name` VARCHAR(20), 
    `major` VARCHAR(20)
);

CREATE TABLE `student`( #创建表,更好的写法
    `student_id` INT,
    `name` VARCHAR(20), 
    `major` VARCHAR(20),
    PRIMARY KEY(`student_id`)
);

DROP TABLE `student` # 表的删除

(2)表的修改

sql 复制代码
# 为表增加新的项GPA,并指定格式为DECIMAL(3,2)
ALTER TABLE `student` ADD `GPA` DECIMAL(3,2)
# 删除表中的项GPA
ALTER TABLE `student` DROP COLUMN `GPA`

# 在表中插入数据,位置要对应
INSERT INTO `student` VALUES(4,'qiqi',NULL)
# 制定顺序插入数据,空的位置会被记为NULL
INSERT INTO `student`(`name`,`major`,`student_id`) VALUES('play','cong',5)
INSERT INTO `student`(`major`,`student_id`) VALUES('hang',6)

(3)其他指令

sql 复制代码
DESCRIBE `student`; #显示表信息(数据类型等)

3.属性约束

示例:

sql 复制代码
CREATE TABLE `student`(
    `student_id` INT AUTO_INCREMENT, # 自动递增+1
    `name` VARCHAR(20) NOT NULL, # 要求不能为NULL
    `major` VARCHAR(20) UNIQUE, # 要求数据不重复
    `GPA` DECIMAL(3,2) DEFAULT 0.00 # 设定默认值
    PRIMARY KEY(`student_id`)
);

4.数据操作

以下代码可能需要

sql 复制代码
SET SQL_SAFE_UPDATES = 0; #来禁用安全模式

(1)数据更新

场景 :参考二、2中创建的表格。将表格student中的列major中的'英语',替换成为'外国语言文学'

sql 复制代码
# 示例1:
UPDATE `student` # 指定要更新的表格
SET `major` = '外国语言文学' # 指定新的数据
WHERE `major` = '英语'; # 条件

# 示例2:
UPDATE `student` # 指定要更新的表格
SET `major` = '外国语言文学' # 指定新的数据
WHERE `student_id` = '3'; # 条件

# 示例3:多个条件(或条件)
UPDATE `student` # 指定要更新的表格
SET `major` = '生化' # 指定新的数据
WHERE `major` = '生物' OR `major` = '化学'; # 条件,与条件AND同理

# 示例4:多个数据
UPDATE `student` # 指定要更新的表格
SET `name`='小芳', `major` = '物理' # 指定新的数据
WHERE `student_id` = '2'; # 条件

# 示例:无条件约束
UPDATE `student` # 指定要更新的表格
SET `major` = '物理' # 指定新的数据,所有数据都会被修改

(2)数据删除

sql 复制代码
# 示例1:
DELETE FROM `student`
WHERE `student_id` = 4;

# 示例2:
DELETE FROM `student`
WHERE `name` = '小惠' AND `major` = '物理';

# 示例3:
DELETE FROM `student`
WHERE `GPA` < 3.50;

# 示例4:清空表格
DELETE FROM `student`

(3)数据查找

sql 复制代码
# 示例1:显示所有表数据
SELECT * FROM `student`; #*表示全部

# 示例2:显示指定行(属性)的数据
SELECT `name`, `major` FROM `student`; 

# 示例3:按照条件排序
SELECT * 
FROM `student`
ORDER BY `GPA`; # 排序条件默认ASC升序,额外增加一个DESC在末尾变为降序

# 示例4:按照多个条件排序
SELECT * 
FROM `student`
ORDER BY `GPA`, `student_id`; # 若GPA一致,则按照student_id排序

# 示例5:显示部分数据
SELECT * 
FROM `student`
LIMIT 2; #只显示前两个数据

# 示例6:按条件显示数据
SELECT * 
FROM `student`
WHERE `major` = '英语'; #只回传符合条件的数据

# 示例7:按条件显示数据IN
SELECT * 
FROM `student`
WHERE `major` IN('英语','历史','语文'); #等同于OR

四、实例:公司资料库

1.初始化

(1)表格创建与关联

sql 复制代码
# 创建表格
CREATE TABLE `employee`(
	`emp_id` INT PRIMARY KEY,
	`name` VARCHAR(20),
	`brith_date` DATE,
	`sex` VARCHAR(1),
	`salary` INT,
	`branch_id` INT,
	`sup_id` INT
);
# 创建表格
CREATE TABLE `branch`(
	`branch_id` INT PRIMARY KEY,
	`branch_name` VARCHAR(20),
	`manager_id` INT,
	FOREIGN KEY (`manager_id`) REFERENCES `employee`(`emp_id`) ON DELETE SET NULL # 建立foreign key
);

# 建立foreign key连接
ALTER TABLE `employee`
ADD FOREIGN KEY(`branch_id`)
REFERENCES `branch`(`branch_id`)
ON DELETE SET NULL;
# 建立foreign key连接
ALTER TABLE `employee`
ADD FOREIGN KEY(`sup_id`)
REFERENCES `employee`(`emp_id`)
ON DELETE SET NULL;

# 创建表格
CREATE TABLE `client`(
	`client_id` INT PRIMARY KEY,
	`client_name` VARCHAR(20),
	`phone` VARCHAR(20)
);

CREATE TABLE `works_with`(
	`emp_id` INT,
	`client_id` INT,
	`total_sales` INT,
	PRIMARY KEY(`emp_id`,`client_id`),
	FOREIGN KEY(`emp_id`) REFERENCES `employee`(`emp_id`) ON DELETE CASCADE,
	FOREIGN KEY(`client_id`) REFERENCES `client`(`client_id`) ON DELETE CASCADE
);

(2)修改数据

branch 表格与employee表格:

sql 复制代码
# 先修改branch表格(防止循环引用出错)
INSERT INTO `branch` VALUES(1,'研发',NULL);
INSERT INTO `branch` VALUES(2,'行政',NULL);
INSERT INTO `branch` VALUES(3,'咨询',NULL);

# 再往employee表格增加数据
INSERT INTO `employee` VALUES(206,'小黄','1998-10-08','F',50000,1,NULL);
INSERT INTO `employee` VALUES(207,'小绿','1998-10-08','M',29000,2,206);
INSERT INTO `employee` VALUES(208,'小黑','1998-10-08','M',35000,3,206);
INSERT INTO `employee` VALUES(209,'小白','1998-10-08','F',39000,3,207);
INSERT INTO `employee` VALUES(210,'小蓝','1998-10-08','F',84000,1,207);

# 最后修改branch表格的数据
UPDATE `branch`
SET `manager_id` = 206
WHERE `branch_id` = 1;
# 最后修改branch表格的数据
UPDATE `branch`
SET `manager_id` = 207
WHERE `branch_id` = 2;
# 最后修改branch表格的数据
UPDATE `branch`
SET `manager_id` = 208
WHERE `branch_id` = 3;

client 表格与works_with表格:

sql 复制代码
# 往client表格新增数据
INSERT INTO `client` VALUES(400,'阿狗','2545156848');
INSERT INTO `client` VALUES(401,'阿猫','48915848');
INSERT INTO `client` VALUES(402,'旺来','2548994518');
INSERT INTO `client` VALUES(403,'露西','1219561');
INSERT INTO `client` VALUES(404,'艾瑞克','51911948');
# 往works_with表格新增数据
INSERT INTO `works_with` VALUES(206,400,'70000');
INSERT INTO `works_with` VALUES(207,401,'24000');
INSERT INTO `works_with` VALUES(208,402,'9800');
INSERT INTO `works_with` VALUES(208,403,'24000');
INSERT INTO `works_with` VALUES(210,404,'87940');

2.数据查找

  1. 取得所有员工资料
sql 复制代码
SELECT * 
FROM `employee`;
  1. 取得所有客户资料
sql 复制代码
SELECT * 
FROM `client`;
  1. 按薪水低到高取得员工资料
sql 复制代码
SELECT * 
FROM `employee`
ORDER BY `salary`;
  1. 取得薪水前3高的员工
sql 复制代码
SELECT * 
FROM `employee`
ORDER BY `salary` DESC
LIMIT 3;
  1. 取得所有员工的名字
sql 复制代码
SELECT `name`
FROM `employee`;
  1. 取得所有员工的性别(不重复)
sql 复制代码
SELECT DISTINCT `sex`
FROM `employee`;

3.数据聚合

  1. 取得员工人数
sql 复制代码
SELECT COUNT(*) FROM `employee`; # 返回员工总人数
SELECT COUNT(`sup_id`) FROM `employee`; # 返回非NULL的sup_id的数量 
  1. 取得所有出生于:1978-01-01之后的女性员工人数
sql 复制代码
SELECT COUNT(*) 
FROM `employee`
WHERE `birth_date` > '1970-01-01' AND `sex` = 'F';
  1. 取得所有员工的平均薪水
sql 复制代码
SELECT AVG(`salary`) 
FROM `employee`
  1. 取得所有员工薪水的总和
sql 复制代码
SELECT SUM(`salary`) 
FROM `employee`
  1. 取得薪水最高的员工
sql 复制代码
SELECT MAX(`salary`) 
FROM `employee`
  1. 取得薪水最低的员工
sql 复制代码
SELECT MIN(`salary`) 
FROM `employee`

4.通配符

% 表示多个通配符;

_ 表示一个通配符。

  1. 取得电话号码尾数是518的客户
sql 复制代码
SELECT * 
FROM `client`
WHERE `phone` LIKE '%518';
  1. 取得姓艾的客户
sql 复制代码
SELECT * 
FROM `client`
WHERE `client_name` LIKE '艾%';
  1. 取得生日在12月的员工
sql 复制代码
SELECT * 
FROM `employee`
WHERE `brith_date` LIKE '_____12%';

5.数据联合 UNION

  1. 员工名字 union 客户名字
sql 复制代码
SELECT `name` # 变量属性要一致
FROM `employee`
UNION
SELECT `client_name`
FROM `client`;
  1. 员工id + 员工名子 union 客户id + 客户名字
sql 复制代码
SELECT `emp_id`,`name` # 变量属性要一致
FROM `employee`
UNION
SELECT `client_id`,`client_name`
FROM `client`;
  1. 员工薪水 union 销售金额
sql 复制代码
SELECT `salary` AS `total_money`
FROM `employee`
UNION
SELECT `total_sales`
FROM `works_with`;

6.数据连接 JOIN

用于连接不同表格。

  • 取得所有部门经理的名字
sql 复制代码
SELECT `emp_id`,`name`,`branch_name`
FROM `employee`
JOIN `branch`
ON `emp_id` = `manager_id`;

# 精确写法,处理同属性名的情况
SELECT `emp_id`,`name`,`branch_name`
FROM `employee`
JOIN `branch`
ON `employee`.`emp_id` = `branch`.`manager_id`; # 精确写法

# 左表无条件显示,右表有条件显示
SELECT `emp_id`,`name`,`branch_name`
FROM `employee`
LEFT JOIN `branch`
ON `employee`.`emp_id` = `branch`.`manager_id`;

# 右表无条件显示,左表有条件显示
SELECT `emp_id`,`name`,`branch_name`
FROM `employee` RIGHT JOIN `branch` # 另一种写法
ON `employee`.`emp_id` = `branch`.`manager_id`;

# 起别名法
SELECT `a`.`emp_id`,`a`.`name`,`b`.`branch_name`
FROM `employee` `a`
RIGHT JOIN `branch` `b`
ON `a`.`emp_id` = `b`.`manager_id`;

7.子查询

  1. 找出研发部门的经理名字
sql 复制代码
SELECT `name`
FROM `employee`
WHERE `emp_id` = (
	SELECT `manager_id`
	FROM `branch`
	WHERE `branch_name` = '研发'
);
  1. 找出对单一客户销售金额超出50000的员工的名字
sql 复制代码
SELECT `name`
FROM `employee`
WHERE `emp_id` = (
	SELECT `emp_id`
	FROM `work_with`
	WHERE `total_sales` > 50000
);

8.ON DELETE

(1)ON DELETE SET NULL

ON DELETE SET NULL含义解释,示例:

sql 复制代码
CREATE TABLE `branch`(
	`branch_id` INT PRIMARY KEY,
	`branch_name` VARCHAR(20),
	`manager_id` INT,
	FOREIGN KEY (`manager_id`) REFERENCES `employee`(`emp_id`) ON DELETE SET NULL # 建立foreign key
);

若employee表格中小绿的数据被删除,branch表格中对应数据置为NULL

(2)ON DELETE CASCADE

ON DELETE CASCADE含义解释,示例:

sql 复制代码
CREATE TABLE `works_with`(
	`emp_id` INT,
	`client_id` INT,
	`total_sales` INT,
	PRIMARY KEY(`emp_id`,`client_id`),
	FOREIGN KEY(`emp_id`) REFERENCES `employee`(`emp_id`) ON DELETE CASCADE,
	FOREIGN KEY(`client_id`) REFERENCES `client`(`client_id`) ON DELETE CASCADE
);

若employee表格中小绿的数据被删除,works_with表格中对应数据同步删除。

注意 :当一个属性同时为 primary key 和 foreign key 时,不能使用ON DELETE SET NULL

五、python连接MySQL

  1. 安装:
bash 复制代码
pip install mysql-connector-python
  1. python代码
python3 复制代码
import mysql.connector
connection = mysql.connector.connect(host = 'localhost',
						port = '3306',
						user = 'root',
						password = 'password')
cursor = connection.cursor()

六、重点解析

1.常用关键字

(1)ON

  • 用于 JOIN 子句中,指定两个表之间的连接条件。
  • 连接条件用于确定如何将两个表的行配对。
  • JOIN有多个条件时,先筛选再连接。

(2)WHERE

  • 用于过滤查询结果集中的行。
  • 可以用于任何查询,不仅限于连接。
  • JOIN有多个条件时,先连接再筛选。
  • 相比ON效率更低,因此JOIN优先使用ON

(3)AS

用来重命名,很方便,如 leetcode 181 题。

sql 复制代码
select `e1`.`name` as `Employee`
from `Employee` as `e1`
join `Employee` as `e2`
on `e1`.`managerId` = `e2`.`id` and e1.salary > e2.salary
; # 这里使用where代替on,结果一致

这里将Employee复制一遍,并分别重命名为e1e2,便于调取操作。

(4)GROUP BY

GROUP BY 子句用于将结果集按一个或多个列进行分组,通常与聚合函数(如 COUNTSUMAVGMAXMIN 等)一起使用,以对每个分组进行计算。

示例,假设有一个如下的数据表:

+----+---------+--------+
| id | product | amount |
+----+---------+--------+
| 1  | A       | 100    |
| 2  | B       | 150    |
| 3  | A       | 200    |
| 4  | B       | 250    |
| 5  | C       | 300    |
+----+---------+--------+

如果想要计算每个产品的销售次数:

sql 复制代码
SELECT product, COUNT(*) as sales_count
FROM Sales
GROUP BY product;

结果:

+---------+-------------+
| product | sales_count |
+---------+-------------+
| A       | 2           |
| B       | 2           |
| C       | 1           |
+---------+-------------+

(5)HAVING

HAVING 子句用于对分组后的结果集进行过滤,通常与 GROUP BY 子句和聚合函数一起使用。HAVING 子句的作用类似于 WHERE 子句,但 WHERE 子句不能用于聚合函数,而 HAVING 子句可以。

继续(4)中的示例:

sql 复制代码
SELECT product
FROM Sales
GROUP BY product
HAVING COUNT(product) > 1;

结果:

+---------+
| product |
+---------+
| A       |
| B       |
+---------+

(6)DELETE

如 leetcode 196 删除重复的电子邮箱:

Person 表:
+----+------------------+
| id | email            |
+----+------------------+
| 1  | john@example.com |
| 2  | bob@example.com  |
| 3  | john@example.com |
+----+------------------+
sql 复制代码
delete `p1`
from `Person` as `p1`, `Person` as `p2`
where `p1`.`email` = `p2`.`email` and `p1`.`id` > `p2`.`id`
; 

(7)OVER

OVER 子句用于窗口函数(也称为分析函数或 OLAP 函数),这些函数允许你在不需要 GROUP BY 子句的情况下对结果集的某些部分进行计算。窗口函数在 SQL 中非常强大,可以用于各种复杂的分析和计算。

窗口函数

  • ROW_NUMBER() 分配一个唯一的行号。
  • RANK() 排名,如果有相同的值,它们将获得相同的排名,并且排名中会有跳跃。
  • DENSE_RANK() 与 RANK() 类似,但排名中没有跳跃。
  • NTILE(M) 将结果集划分为指定数量的桶,并为每一行分配一个桶号。桶的数量由参数指定。
  • SUM() 计算分区内指定列的总和。
  • AVG() 计算分区内指定列的平均值。
  • COUNT() 计算分区内的行数。
  • MAX() 计算分区内指定列的最大值。
  • MIN() 计算分区内指定列的最小值。

示例

sql 复制代码
窗口函数() OVER ([PARTITION BY 分区列] [ORDER BY 排序列]) # 基本用法

假设有一个名为 employees 的表,包含以下列:id、name、department 和 salary。

  1. 使用 ROW_NUMBER() 计算每个部门中员工的行号
sql 复制代码
SELECT 
    id,
    name,
    department,
    salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
FROM 
    employees;
  1. 使用 SUM() 计算每个部门的累计工资
sql 复制代码
SELECT 
    id,
    name,
    department,
    salary,
    SUM(salary) OVER (PARTITION BY department ORDER BY salary) AS cumulative_salary
FROM 
    employees;
  1. 使用 RANK() 计算每个部门中员工的排名
sql 复制代码
SELECT 
    id,
    name,
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank
FROM 
    employees;

注意PARTITION BY 用来划分分区。比如说 RANK() 函数给高考排名,PARTITION BY 可以根据文理科来划分区域,文科和理科各自单独排名。ORDER BY则是排名的依据。

2.易错点

(1)IN 和 NOT IN

需要一个列表或子查询结果,而不是一个表的列。

示例

Customers table:
+----+-------+
| id | name  |
+----+-------+
| 1  | Joe   |
| 2  | Henry |
| 3  | Sam   |
| 4  | Max   |
+----+-------+
Orders table:
+----+------------+
| id | customerId |
+----+------------+
| 1  | 3          |
| 2  | 1          |
+----+------------+

下面展示正确 写法和错误写法:

sql 复制代码
select customers.name as 'Customers'
from customers
where customers.id not in # 正确写法!!!
(
    select customerid from orders
);

# 错误写法!!!
where customers.id not in orders.customerid;

(2)时间计算

与常规的整数计算不同。

sql 复制代码
# unit可以是SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR
TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2) # 计算两个时间的差值
TIMESTAMPADD(unit, interval, datetime_expr) # 计算该时间加上一定时间后的时间

DATEDIFF(date_expr1, date_expr2) # 计算两个时间的差值
DATE_ADD(date, INTERVAL expr unit) # 指定日期加上时间间隔
DATE_SUB(date, INTERVAL expr unit) # 指定日期减去时间间隔

ADDDATE(date, INTERVAL expr unit) # 指定日期加上时间间隔
SUBDATE(date, INTERVAL expr unit) # 指定日期减去时间间隔
相关推荐
林的快手24 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
stm 学习ing40 分钟前
HDLBits训练6
经验分享·笔记·fpga开发·fpga·eda·verilog hdl·vhdl
HEU_firejef1 小时前
Redis——缓存预热+缓存雪崩+缓存击穿+缓存穿透
数据库·redis·缓存
stm 学习ing1 小时前
HDLBits训练4
经验分享·笔记·fpga开发·课程设计·fpga·eda·verilog hdl
炸毛的飞鼠1 小时前
汇编语言学习
笔记·学习
风无雨2 小时前
react杂乱笔记(一)
前端·笔记·react.js
胡西风_foxww2 小时前
【ES6复习笔记】Class类(15)
javascript·笔记·es6·继承··class·静态成员
KELLENSHAW2 小时前
MySQL45讲 第三十七讲 什么时候会使用内部临时表?——阅读总结
数据库·mysql
四七伵2 小时前
MySQL外键类型与应用场景总结:优缺点一目了然
mysql
SelectDB2 小时前
飞轮科技荣获中国电信星海大数据最佳合作伙伴奖!
大数据·数据库·数据分析