数据库,就是一类专门负责管理(增删查改)数据的软件
数据库大体可以分为 关系型数据库 和 非关系型数据库
关系型数据库(RDBMS):
是指采用了关系模型来组织数据的数据库。 简单来说,关系模型指的就是二维表格模型,而一个
我们主要学习的是关系型数据库,有很多具体的实现(如MySQL,Oracle,SQL Server,SQLite等)
但不管哪个数据库,其核心的东西都是 SQL(编程语言)
下面我们就正式进入MySQL的学习
请参考
当我们在开始菜单看到有这两个
并且打开后
看到如上图所示的样子,证明你的MySQL已经安装完成了
MySQL是一个“客户端服务器” 结构的程序
一个服务器同一时刻可能要给多个客户端提供服务
因为服务器不确定客户端啥时候有需求,服务器常常要长时间运行,甚至是7*42小时
当我们安装了MySQL,其实是既安装了客户端(客户端也有很多种版本,如命令行,图形化界面等,还可以自己写代码实现客户端),又安装了服务器
上图的就是命令行客户端
我们在设置中看到的这个就说明了MySQL是有服务器的
当然客户端和服务器也可以是在不同主机上
存储和管理数据都是有MySQL服务器负责的,因此MySQL服务器要比MySQL客户端复杂很多,甚至可认为MySQL服务器就是MySQL的主体
MySQL服务器程序简图
有几点需要说明
一个MySQL服务器可能包含多个“数据库”
此处的“数据库”其实是==“数据集合”==(逻辑上的),这里面放了一些具有关联关系的数据
每个数据库(数据集合)里面有很多个“数据表”(类似于我们日常看到的表格)
MySQL服务器组织数据的方式可以概括为: 数据库 --> 数据表 --> 行 --> 列
我们都知道一台计算机有以下几部分组成:
而存储器:用来存储数据的设备,它分为 内存 和 外存
内存,大家一定都不陌生。外存便是我们常说的”硬盘“,U盘,光盘,软盘等
这些都是我们学习数据库的一些先驱知识,掌握了这些知识后,学习的过程中有一些知识会更容易理解
这里我们介绍的是MySQL的实际操作(围绕SQL语句展开)
create database 数据库名;
创建数据库可以指定字符集和校验规则
字符集描述了存储的数据支持什么样的字符
校验规则描述了当前字符间该如何进行比较
当我们创建数据库没有指定字符集和校验规则时,系统使用默认字符集:utf8,校验规则
是:utf8_ general_ ci
show databases;
可查看当前存在的数据库
要想针对某个数据库进行具体操作(存入数据/查询数据等)就需要先选中数据库
use 数据库名;
drop database 数据库名;
数据库删除以后,内部看不到对应的数据库,里面的表和数据全部被删除
需要注意的是,删除数据库的操作十分危险
千万不要在公司的服务器上进行删除,尤其是不要在生产环境服务器上删除,产生的后果可能十分严重
介绍数据表的操作之前,我们先说说MySQL的数据类型
MySQL是一个关系型数据库,特点是通过表的形式来组织数据
数据类型一方面能方便我们对数据进行处理,一方面也能针对数据进行校验和检查
分为整型和浮点型
数据类型 | 大小 | 说明 | 对应java类型 |
---|---|---|---|
BIT[ (M) ] | M指定位 数,默认 为1 | 二进制数,M范围从1到64, 存储数值范围从0到2^M-1 | 常用Boolean对应BIT,此时 默认是1位,即只能存0和1 |
TINYINT | 1字节 | Byte | |
SMALLINT | 2字节 | Short | |
INT | 4字节 | Integer | |
BIGINT | 8字节 | Long | |
FLOAT(M, D) | 4字节 | 单精度,M指定长度,D指定 小数位数。会发生精度丢失 | Float |
DOUBLE(M, D) | 8字节 | Double | |
DECIMAL(M, D) | M/D最大 值+2 | 双精度,M指定长度,D表示 小数点位数。精确数值 | BigDecimal |
NUMERIC(M, D) | M/D最大 值+2 | 和DECIMAL一样 | BigDecimal |
注:DECIMAL相当于通过字符串的方式来表示浮点数。优势就是能够精确表示,精确计算。但是劣势就是计算时候消耗的时间更多,存储空间也更多。所以我们除非是特别需要,才考虑使用DECIMAL。
数据类型 | 大小 | 说明 | 对应java类型 |
---|---|---|---|
VARCHAR (SIZE) | 0-65,535字节 | 可变长度字符串 | String |
TEXT | 0-65,535字节 | 长文本数据 | String |
MEDIUMTEXT | 0-16 777 215字节 | 中等长度文本数据 | String |
BLOB | 0-65,535字节 | 二进制形式的长文本数据 | byte[] |
注意:
数据类型 | 大 小 | 说明 | 对应java类型 |
---|---|---|---|
DATETIME | 8 字 节 | 范围从1000到9999年,不会进行时区的 检索及转换。 | java.util.Date、 java.sql.Timestamp |
TIMESTAMP | 4 字 节 | 范围从1970到2038年,自动检索当前时 区并进行转换。 | java.util.Date、 java.sql.Timestamp |
时间戳:以1970年1月1日0时0分0秒作为基准时刻,计算当前时刻和基准时刻的秒数之差。
这么多数据类型,其实我们最常用的是
介绍完了数据类型,下面正式进入数据表的操作吧
create table 表名(列名 类型,列名 类型... )
要想创建表,得先有一个数据库,再选中这个数据库
例如:
create table student(id int,name varchar(20))
这样我们就创建了这样的表
我们看一下怎么操作
注:
再选中数据库的前提下
show tables;
可以查看表里的列和类型
desc 表名;
desc是describe的缩写
drop 表名;
删除表的操作也是十分危险的,甚至危害比删除库更大!
MySQL的工作就是组织管理数据,先保存,保存好了后续就方便我们进行增删查改
增删查改的前提是:已经把数据库创建完成,并且选中了,表也准备就绪
insert into 表名 values(值,值,值...)
注意
此处的值的个数要和表的列数匹配,值的类型也要和列的类型匹配
注意:在SQL中表示字符串(SQL中没有”字符类型“),可以使用单引号==’ ',也可以使用双引号" "==,它们是等价的关系
我们的值的个数与表的列数不匹配,就会报错,如图
数据库中,如果要表示中文,需要先明确字符编码(字符集)
MySQL默认的字符集,叫做拉丁文,它是不支持中文的
为了能够存储中文,我们需要把字符集改成UTF-8
而修改MySQL字符集的方法有很多种,这里介绍一种一劳永逸的方法 ——修改MySQL的配置文件
第一步、我们需要先确认当前数据库的字符集
show variables like 'character%';
第二步、找到配置文件 my.ini
这个文件不好找,我们介绍一种方法
a、打开开始菜单中的文件位置
b、右键,点击属性,找到”目标“
c、把”目标“中的内容拷贝下来,这里就是MySQL的可执行程序路径和配置文件路径
我们只需要拷贝这句话
d、按照这个路径,就找到了配置文件 my.ini
第三步、修改配置文件
a、为了防止我们修改配置文件操作失败,我们要先进行备份,(备份是一个很好的习惯!!)
b、编辑 **ini ** 文件(使用记事本打开即可)
我们只需要找到两处
第一处:
第二处:
注意两侧不要有空格
第四步、配置文件不是改了就立即生效的,还需要做一些额外工作
a、重启MySQL服务器,不重启肯定不会生效!
在开始菜单找到服务,然后找到MySQL,右键,重启
重启之后看到 显示 正在运行,说明修改成功
如果是其它内容,如 启动中…,则说明重启失败
失败的最大原因就是配置文件修改错了
b、修改配置文件对于已经创建好的数据库是不会生效的
必须删除旧的,重新建库建表
1、insert插入的时候可以指定行插入,不一定非得把这一行的所有列都插入数据
制定了name这一列插入,其它未被指定的列,填入的值就是这一列的默认值,默认的默认值就是啥都不填也就是null
2、insert语句还可以一次插入多条记录
在values后面,带有多个 ( ),每个 ( )之间 用逗号, 来分割
如果要插入多条记录,我们更推荐一次插入多条,而不是一次一条多次插入,因为更快
直接把整个表里的数据都查询出来
select * from 表名;
* 是通配符,表示匹配任意的列(所有列)
我们看到的只是一个呈现在客户端上的==”临时表“==,而不是服务器上数据的本体
如果数据量特别大,采取这样的操作,就极有可能把磁盘IO吃满,或者把网络带宽吃满,导致”卡了“
这会影响用户的体验,假设我们感觉”卡了“,可以按
ctrl+c
来终止操作
当我们省略掉一些不必要的列时,就可以节省大量的磁盘IO和网络带宽了
select 列名,列名,列名...from 表名;
我们需要在强调一便!
我们看到的只是一个呈现在客户端上的==”临时表“==,而不是服务器上数据的本体
所以虽然我们只看到了一列,但并不代表只有一列!
比如这样的表
我们可以创建一个新的表方便计算,也就是 带有表达式的查询
我们又要回到刚刚那个老生常谈的重点知识
我们看到的只是一个呈现在客户端上的==”临时表“==,而不是服务器上数据的本体
也就是,这个表上的数据即使超过了我们定义的有效数字的范围,也没关系,只要服务器本体不超过就可以
我们证明一下这个结论
但是我们尽量不要把不同类型的数据相加减,如字符串和数值,会报警告
我们使用show warnings来查看警告内容
show warnings
还有一个小细节:SQL中,如果拿NULL和其他类型进行混合运算,结果仍是NULL
select distinct 列名 from 表名;
这样能把查询结果相同的行,合并成一个
distinct后面也能指定多个列,但必须是多个列中每个列的值都相同才会视为相同(才会去重)
查询过程中,对于查询到的结果进行排序(针对临时表排序,对于数据库上原来存的数据没有影响)
select 列名 from 表名 order by 列名;
默认是升序排序(asc),我们也可以进行降序排序
select 列名 from 表名 order by 列名 desc;
我们也可以对别名排序
order by 进行排序的时候,还可以指定多个列来进行排序
当指定多个列进行排序的时候,就相当于,先以第一个列为标准进行比较。如果第一列不分胜负,再按照第二列进行比较
select操作中,如果没有使用order by,那么查询结果的顺序是不可以依赖的(不确定的)
指定条件,对于查询结果进行筛选
在进行查询的时候
select * from 表名 where 条件;
我们引入了where字句,针对查询结果进行筛选
筛选可以理解成,对于查询结果进行依次遍历,把对应的查询结果带入到条件中,
若条件成立,则把这个记录放到最终查询结果中,条件不成立,则直接舍弃掉,不作为最终结果
(此处的条件其实就和 if 里的语句差不多)
1.比较运算符
运算符 | 说明 |
---|---|
>, >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1) |
!=, <> | 不等于 |
BETWEEN a0 AND a1 | 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1) |
IN (option, …) | 如果是 option 中的任意一个,返回 TRUE(1) |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
LIKE | 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字 符 |
注意:SQL中 ‘ = ’ 号可不是赋值了,就是等于
2.逻辑运算符
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0) |
我们进行条件查询时,就是通过将上述运算符组合完成的
小细节:在这里,别名并不能作为筛选条件使用
注:
案例:
-- 查询语文成绩大于80分,且英语成绩大于80分的同学
SELECT * FROM exam_result WHERE chinese > 80 and english > 80;
-- 查询语文成绩大于80分,或英语成绩大于80分的同学
SELECT * FROM exam_result WHERE chinese > 80 or english > 80;
-- 观察AND 和 OR 的优先级:(先算 and 后算 or)
SELECT * FROM exam_result WHERE chinese > 80 or math>70 and english > 70;
SELECT * FROM exam_result WHERE (chinese > 80 or math>70) and english > 70;
范围查询:
1.BETWEEN … AND …
-- 查询语文成绩在 [80, 90] 分的同学及语文成绩(闭区间)
SELECT name, chinese FROM exam_result WHERE chinese BETWEEN 80 AND 90;
-- 使用 AND 也可以实现
SELECT name, chinese FROM exam_result WHERE chinese >= 80 AND chinese <= 90;
-- 时间信息也是可以用between...and...的。
select * from article where create_date between '2019-01-01 10:30:00' and '2019-11-10 16:02:00';
2.IN
-- 查询数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
SELECT name, math FROM exam_result WHERE math IN (58, 59, 98, 99);
-- 使用 OR 也可以实现
SELECT name, math FROM exam_result WHERE math = 58 OR math = 59 OR math = 98 OR math = 99;
-- % 匹配任意多个(包括 0 个)字符
SELECT name FROM exam_result WHERE name LIKE '孙%';-- 匹配到孙悟空、孙权
-- _ 匹配严格的一个任意字符
SELECT name FROM exam_result WHERE name LIKE '孙_';-- 匹配到孙权
SELECT name FROM exam_result WHERE name LIKE '孙__';-- 匹配到孙悟空
模糊查询需要用到通配符,% 可以用来代替任意个任意字符,_ 可以用来代替一个任意字符
类似的
%孙 匹配以 孙 结尾的数据
%孙% 匹配包含孙的数据
% 匹配任意数据
-- 查询 qq_mail 已知的同学姓名
SELECT name, qq_mail FROM student WHERE qq_mail IS NOT NULL;
-- 查询 qq_mail 未知的同学姓名
SELECT name, qq_mail FROM student WHERE qq_mail IS NULL;
SELECT name, qq_mail FROM student WHERE qq_mail <=> NULL; -- 也可以
让查询结果,只取出其中的一个部分,从而能够降低开销,加快查询速度
比如论坛类的网站,展示帖子的时候往往会有分页展示的效果
一个论坛可能有几千/几万的帖子,打开页面的时候,其实只能先看到其中的一小部分(比如只显示前20条记录)
-- 起始下标为 0
-- 从 0 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
-- 从 s 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
-- 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
案例一:显示前三名的成绩
select name,chinese + english + math as total from exam_result order by total desc limit 3;
案例二:按 id 进行分页,每页 3 条记录,分别显示 第 1、2、3 页
-- 第 1 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3
OFFSET 0;
-- 第 2 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3
OFFSET 3;
-- 第 3 页,如果结果不足 3 个,不会有影响
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3
OFFSET 6;
后续如果要针对生产环境的数据库进行查询,记得最好都加上limit,防止出现意外导致服务器挂了~~
此处的修改时针对数据库服务器进行的!
这样的修改是持续有效的。
update 表名 set 列名 = 值,列名 = 值...[WHERE ...] [ORDER BY ...] [LIMIT ...]
核心信息:针对哪个表,表里的哪些行,哪些列,改成啥样的值
案例:
-- 将孙悟空同学的数学成绩变更为 80 分
UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
-- 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
UPDATE exam_result SET math = 60, chinese = 70 WHERE name = '曹孟德';
-- 将总成绩倒数前三的 3 位同学的数学成绩减去 30 分
UPDATE exam_result SET math = math - 30 ORDER BY chinese + math + english LIMIT 3;
-- 将所有同学的语文成绩更新为原来的 2 倍
UPDATE exam_result SET chinese = chinese * 2;
修改操作,是针对条件筛选之后剩下的数据进行的修改
如果没写条件,意味着就是针对所有的行都修改!
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
delete 只是把表的内容清空但是表还在,但是drop是把表连带数据一起删除
案例:
-- 删除孙悟空同学的考试成绩
DELETE FROM exam_result WHERE name = '孙悟空';
-- 删除整张表数据
-- 准备测试表
DROP TABLE IF EXISTS for_delete;
CREATE TABLE for_delete (
id INT,
name VARCHAR(20)
);
-- 插入测试数据
INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');
-- 删除整表数据
DELETE FROM for_delete;
‘孙悟空’;
– 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
UPDATE exam_result SET math = 60, chinese = 70 WHERE name = ‘曹孟德’;
– 将总成绩倒数前三的 3 位同学的数学成绩减去 30 分
UPDATE exam_result SET math = math - 30 ORDER BY chinese + math + english LIMIT 3;
– 将所有同学的语文成绩更新为原来的 2 倍
UPDATE exam_result SET chinese = chinese * 2;
修改操作,是针对条件筛选之后**剩下的数据**进行的修改
如果没写条件,意味着就是针对所有的行都修改!
##### 11 删除(Delete)
```sql
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
delete 只是把表的内容清空但是表还在,但是drop是把表连带数据一起删除
案例:
-- 删除孙悟空同学的考试成绩
DELETE FROM exam_result WHERE name = '孙悟空';
-- 删除整张表数据
-- 准备测试表
DROP TABLE IF EXISTS for_delete;
CREATE TABLE for_delete (
id INT,
name VARCHAR(20)
);
-- 插入测试数据
INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');
-- 删除整表数据
DELETE FROM for_delete;