MySQL基础学习笔记
一、数据库基本概念
1.1 数据库 - Database
从字面意思看,数据库就是一个存储数据的仓库。从计算机的角度来讲,数据库(Datebase)是按照数据结构来组织、存储和管理数据的仓库。
简单来说,可以将数据库视为电子化的一个文件柜。用户可以对文件中的数据进行新增、更新和删除等操作。
数据库中的一些常见术语:
- 实体与实体集:客观存在并相互区别的事物。可客观理解为类似于面向对象中的对象,但又不完全相同。而实体集就是这些事物的集合。
- 属性:实体所具有的某一特性。可类比于面向对象中对象的属性,即对象的成员变量。
- 联系与联系集:实体与实体之间的关系,而联系集就是这些关系的集合。
- 联系一般分为三种,分别为一对一,一对多和多对多
- 比如学生实体与班级实体,就是一对多,即一个学生只属于一个班级,而一个班级里有多个学生
1.2 数据库管理系统 - DBMS
管理关系型数据库的计算机软件就是关系数据库管理系统。常用的关系数据库管理软件有Oracle、MySQL、SQL Server等。
这里以MySQL的学习为主。
1.3 关系型数据库 - RDBMS
所谓关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。简单说:关系型数据库是由多张能互相联接的二维行列表格组成的数据库。
基于关系型数据库的管理系统,我们称之为关系数据库管理系统(RDBMS)。
RDBMS的特点:
- 数据以表格的形式出现
- 每行为各种记录名称
- 每列为记录名称所对应的数据域
- 许多的行和列组成一张表单
- 若干的表单组成database
RDBMS中的一些常见术语:
- 数据表、列、行:如下图一个简单的学生表所示
-
数据库:类似于上图中学生表一样的很多个表的集合。
-
冗余:存储两倍的数据,冗余降低了性能,但提高的数据的安全性。
- 简单理解就是当一个字段在A表中有,而在B表中也有的时候,就称之为冗余
- 为什么需要设置冗余呢?详见解释:http://blog.csdn.net/small_whale/article/details/52468193
-
主键:唯一标识数据表的一列或多列的组合。
-
外键:关联其他表的列。
-
索引:用于提高访问数据库表中特定信息的速度。索引是对数据库表中一列或多列的值进行排序的一种结构。可类比于书籍中的目录,可提高我们查询的效率。
二、E-R 模型
实体 - 联系模型,就是 E-R 模型。它给我们提供了一种不受任何 DBMS 约束的面向用户的表达方法。在数据库设计中被广泛用作数据建模的工具。
E-R 模型的构成成分是实体集、属性和联系集。通过 E-R 模型,我们能得到一个较为清晰的关于整个数据结构的关系图,因为 E-R 模型也称为 E-R 图。
E-R 模型的表示方法:
- 矩形框表示实体,实体名写在矩形框内。
- 椭圆表示实体的属性,属性名写在椭圆内,并用无向边,即直线与其对应的实体连接。
- 菱形表示实体间的联系,联系名写在菱形框内,将有联系的两个实体分别用无向边与菱形相连,并在连线上标明联系类形,即 1 - 1、 1 - N、M - N 。
简单 E-R 图示例:
三、SQL 语句简介
3.1 什么是 SQL
SQL,全称是 Structured Query Language,即结构化查询语言,它是一种特殊的编程语言,专用于对数据库进行操作而设计的,用于对数据库进行增、删、改、查等操作。
3.2 SQL 分类
- 数据定义语言,简称为 DDL(Data Definition Language) ,用来定义数据库对象,如数据库表、列等。关键字包括:create,alter,drop 等。
- 数据操作语言,简称为 DML(Data Manipulation Language) ,用来对数据库表进行操作。关键字包括:insert,delete,update 等。
- 数据控制语言,简称为 DCL(Data Control Language) ,用来定义数据库的访问权限和安全级别以及创建用户。
- 数据查询语言,简称为 DQL(Data Query Language) ,用来查询数据库表的记录。关键字包括:select,from,where等。
3.3 SQL 的通用语法
- SQL 语句通常以分号结尾,它可以单行或多行进行书写
- 可以使用 /**/、—、#的方式进行注释
四、MySQL
MySQL是当前最流行的关系型数据库管理系统之一。
3.1 mac 下 MySQL 的安装
mac下安装软件一般有两种方式,一是在官网上下载安装包,像安装普通软件一样进行安装;另一种则是使用 mac 上的包管理器 homebrew 来进行安装。
两种安装方式可参考:
https://www.jianshu.com/p/fd3aae701db9
安装完后输入:mysql -u root -p,回车后输入密码即可登录 MySQL 命令行界面。
3.2 MySQL 常用数据类型
MySQL 中常见数据类型如下表所示:
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
TINYINT | 1字节 | (-128, 127) | (0, 255) | 小整数值 |
INT | 4字节 | (-2^31, 2^31-1) | (0, 2^32-1) | 较大整数值 |
BIGINT | 8字节 | (-2^65, 2^65-1) | (0, 2^64-1) | 大整数值 |
FLOAT | 4字节 | 浮点数 | ||
DOUBLE | 8字节 | 浮点数 | ||
DATE | 3字节 | YYYY-MM-DD | ||
TIME | 3字节 | HH:MM:SS | ||
VARCHAR | 0-65535字节 | 可变长度字符串 | ||
ENUM | 枚举类型 |
详细可参考:
http://www.runoob.com/mysql/mysql-data-types.html
3.3 简单的 SQL 语句
MySQL中的SQL语句是不区分大小写的,推荐 SQL 关键字使用大写。
这里以在一个 test 数据库中创建一个学生表为例。学生有学号、姓名、性别、年龄四个属性。
- 创建数据库
-- 语法:CREATE DATABSE database_name;
CREATE DATABASE test;
- 查看已有的数据库
SHOW DATABASE;
- 选择一个数据库或者切换数据库
-- 语法:USE database_name;
USE test;
- 查看当前选择的数据库
-- 第一种方式
SELECT DATABASE();
-- 第二种方式,在命令行模式下输入
status;
-- 会显示当前 MySQL 的一些基本情况,包括连接信息等
-- 其中有一项是 Current database 表示当前数据库
- 创建数据表
-- 语法:CREATE TABLE table_name (col_name1 col_type1, ... col_namen col_typen )
-- ENGINE(引擎)=InnoDB DEFAULT CHARSET=utf8 可省略
-- 在创建数据表时,最好指定表的编码
CREATE TABLE student (
-- INT UNSIGNED 表示无符号整数,即只有正整数和0
-- AUTO_INCREMENT 表示自动增长,即我们在插入数据时不用指定这个属性的值,指定了也没用
-- PRIMARY KEY 指定主键
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20),
gender ENUM('男', '女', '保密'),
age INT
);
INSERT INTO test(id, k, v) VALUES(1, 'a', '0'), (1, 'b', 'x'), (1, 'c', '9'), (1, 'ab', 'c'), (1, 'set', 'aweg');
- 查看创建的数据表
-- 语法:SHOW CREATE TABLE table_name;
-- 会显示表的创建语句
SHOW CREATE TABLE student;
-- 语法:DESC table_name;
-- 会以表格的形式展示表中的字段及字段的类型等信息
DESC student;
- 修改数据表结构
-- ALTER TABLE tabel_name operation[ADD, MODIFY, CHANGE, DROP, CHARACTER SET]
-- 给学生表添加列 班级号 - ADD
-- 语法:ALTER TABLE table_name ADD new_col_name type;
ALTER TABLE student ADD class_id int;
-- 修改学生表中学生名字字段的类型,并添加约束不能为空 - MODIFY
-- 语法:ALTER TABLE table_name MODIFY col_name new type or new retriction;
ALTER TABLE student MODIFY name VARCHAR(50) NOT NULL;
-- 修改学生表中的表名,将 class_id 改为 cls_id - CHANGE
-- 语法:ALTER TABLE table_name change old_col_name new_col_name new_col_type;
ALTER TABLE student CHANGE class_id cls_id INT UNSIGNED;
-- 删除学生中的班级号 cls_id 列
-- 语法:ALTER TABLE table_name DROP col_name;
ALTER TABLE student DROP cls_id;
-- 修改表的字符集
-- 语法:ALTER TABLE table_name CHARACTER SET new_character;
ALTER TABLE student CHARACTER SET gbk;
- 插入数据
-- 语法:INSERT INTO table_name (field1, field2,...fieldn) VALUES (v1, v2,...vn), (vv1, vv2,...,vvn);
INSERT INTO student(name, gender, age) VALUES('Demon', '男', 18), ('Semon', '女', 18)
,('haha', '男', 16), ('hehe', '男', 17), ('aaa', '女', 26);
- 查询数据
-- SELECT v1, v2... FROM table_name WHERE conditions;
-- * 表示查询所有字段,一般建议写出查询的字段名称,这样更加容易阅读
SELECT * FROM student;
-- 查询性别为男的学生
SELECT * FROM student WHERE gender = '男';
-- 查询语句是 SQL 语句中最复杂的,我们一般在编写 SQL 语句时都是写的查询语句
- LIKE 查询
-- 使用 LIKE 关键字可以对字符串进行模糊查询
-- LIKE '_XXX'; 其中下划线 _ 占位,表示任意一个字符
-- 查询学生表中以任意一个字符开头,但是以 'emon' 结尾的学生信息
SELECT * FROM student WHERE name LIKE '_semon';
-- LIKE '%XXX'; 其中 % 表示任意一串字符,% 是与 LIKE 关键字最常用的组合
-- 查询学生表中姓名包含 'mo' 的学生信息
SELECT * FROM student WHERE name LIKE '%mo%';
- 条件查询
-- 大于(>),小于(<),大于等于(>=),不等于(!=)或(<>)
-- 使用 AND 表示与
-- 查询学生表中性别为男并且年龄大于18的学生信息
SELECT * FROM student WHERE gender = '男' AND age > 18;
-- 使用 OR 表示或
-- 查询学生表中性别为女或者年龄不等于17的学生信息
SELECT * FROM student WHERE gender = '女' OR age <> 17;
SELECT * FROM student WHERE gender = '女' OR age != 17;
- 修改数据
-- UPDATE table_name SET f1 = v1, f2 = v2... WHERE conditions;
-- 将性别为男的学生的年龄修改为20
UPDATE student SET age = 20 WHERE gender = '男';
- 数据排序
-- 语法:SELECT f1,f2.. FROM table_name WHERE condifitons ORDER BY f1,f2.. [ASC [DESC]]
-- ASC 表示升序,DESC 表示降序,默认是 ASC,可省略。
-- 将学生数据信息按照年龄升序排序
SELECT * FROM student ORDER BY age [ASC];
-- 降序
SELECT * FROM student ORDER BY age DESC;
- 删除数据行
-- 语法:DELETE FROM table_name WHERE conditions;
-- 删除性别为男的学生
DELETE FROM student WHERE gender = '男';
- 修改数据库表名
RENAME TABLE old_table_name TO new_table_name;
- 删除数据表
DROP TABLE table_name;
- 删除数据库
-- 在已经登录 MySQL 后:
DROP DATABASE database_name;
-- 如果没登录前:
mysqladmin -u root -p drop database_name;
-- 回车后输入密码
3.4 聚合函数
使用聚合函数的基础就是使用分组语句,使用语法如下:
-- 语法 SELECT f1,f2.. , function(fn) FROM ... WHERE ... GROUP BY f1,f2...
-- 注意 SELECT 后的属性要和 GROUP BY 中的一致,只能比后面的少,不能超过,否则会报错
-- 查询学生信息中有哪些年龄段的学生
SELECT age FROM student GROUP BY age;
常见的聚合函数如下几种:
- AVG:求平均值
-- 在 GROUP BY 语句中,SELECT 后可以接受 function(fn)
-- 这里的 function 就是聚合函数
-- function 后接受的属性可以是任意属性
-- 求不同性别学生年龄的平均值
SELECT gender, AVG(age) FROM student GROUP BY gender;
- COUNT:求总个数
-- 求不同性别学生的总人数
SELECT gender, count(*) FROM student GROUP BY gender;
- MIN / MAX:求最小或最大值
-- 求不同性别下最大的年龄
SELECT MAX(age),gender FROM student GROUP BY gender;
- SUM:求和
-- 求不同性别下的年龄总和
SELECT SUM(age), gender FROM student GROUP BY gender;
3.5 表关联查询
准备数据,上面已经建立了一个学生表,学生应该隶属于一个班级,我们再建立一个班级表 class ,班级表的字段有班级编号、班级名称。
-- 创建班级数据库表
CREATE TABLE class (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20));
-- 插入数据
INSERT INTO class(name) VALUES ('班级一'), ('班级三'), ('班级二'), ('班级四');
-- 设置外键
ALTER TABLE student ADD CONSTRAINT FK_ID FOREIGN KEY(class_id) REFERENCES class(id);
-- 清空学生表的数据,并重新插入测试数据
DELETE FROM student;
INSERT INTO student(name, gender, age, class_id) VALUES('Demon', '男', 18, 1), ('Semon', '女', 18, 1)
,('haha', '男', 16, 2), ('hehe', '男', 17, 3), ('aaa', '女', 26, 3);
INSERT INTO student(name, gender, age) VALUES('eee', '男', 18);
- 内联 - INNER JOIN
-- 内联的意思是 A 与 B 关联,A 与 B 都有的数据
-- 语法:SELECT ... FROM A INNER JOIN B ON conditions WHERE conditions;
-- INNER 可以省略
-- 查询学生分别在哪些班级
-- AS 表示别名
SELECT s.id AS '学号', s.name AS '学生姓名', c.name AS '班级名称' FROM student AS s JOIN class AS c ON s.class_id = c.id;
- 左关联与右关联 - LEFT JOIN or REIGHT JOIN
-- 左关联的意思是 A 与 B 关联,则以 A 中的数据为主,A的数据会显示完整
-- 右关联的意思是 A 与 B 关联,则以 B 中的数据为主,B的数据会显示完整
-- 查询班级的分配情况,这样无论班级有没有安排学生,都需要显示
SELECT c.id AS '班级编号', c.name AS '班级名称', s.name AS '学生姓名' FROM class AS c LEFT JOIN student AS s ON c.id = s.class_id;
SELECT c.id AS '班级编号', c.name AS '班级名称', s.name AS '学生姓名' FROM student AS s RIGHT JOIN class AS c ON c.id = s.class_id;
3.6 子查询
子查询的概念就是查询嵌套,简单说就是 SELECT 后或者 WHERE 条件后依然嵌套有 SELECT 语句。其实也很好理解,因为 FROM 关键字后面接受的是一个表,而一个表其实就是一个数据集,而我们使用 SELECT 语句查询得到就是一个数据集。所以我们只需要简单地将子查询里的 SELECT 语句单独看成一个数据表就能简化整个查询语句了。
-- 一个简单的例子
-- 查询年龄最大的那个学生的姓名
/*
因为使用 MAX() 函数之后,不能再查询其他的字段,和分组的情况一样
所以我们需要分两步来实现:
1. 先查询出最大的学生年龄
2. 然后在查询条件里加上年龄等于查询出的最大年龄
*/
-- 查询出最大的学生年龄
SELECT MAX(age) FROM student;
-- 查询年龄等于最大年龄的学生姓名
SELECT name FROM student WHERE age = (SELECT MAX(age) FROM student);
后面会继续更新 MySQL 高级,包括函数、视图、存储过程等。还有 Python 与 MySQL 的交互。MongoDB与redis等。
如有问题,可加小编微信 Demon-5203