学完了MySQL基础部分,然后进行复习巩固,就写了这篇博客(好累!!),jdbc部分还没写完,就先发这么多吧!
MySQL 是一个 “关系数据库”,通过表的形式来组织数据;
表的特点是"特别整齐",
每一行,列数都是一样的;
每一列,数据都是同类的(数据类型相同).
数据类型:
一方面能够方便我们对数据进行处理;
一方面也能够针对数据进行校验和检查.
| 数据类型 | 大小 | 说明 | 对应的Java类型 | 对应的C类型 |
|---|---|---|---|---|
| BIT[(M)] | M指定位数,默认为1 | 二进制数,M:1 ~ 64,存储范围,0 ~ 2M-1 | 常用Boolean对应BIT,此时默认为1位,即只能存储0和1 | char[] |
| TINYINT | 1字节 | Byte | signed char | |
| SMALLINT | 2字节 | Short | short int | |
| INT | 4字节 | integer | int | |
| BIGINT | 8字节 | Long | long long int | |
| FLOAT(M,D) | 4字节 | 单精度,M指定长度,D指定精度位数,会发生精度丢失 | Float | float |
| DOUBLE(M,D) | 8字节 | Double | double | |
| DECIMAL(M,D) | M+2 | 双精度,M指定长度,D指定小数点位数,精确数值 | BigDecimal | char[] |
| NUMERIC(M,D) | M+2 | 同上 | BigDecimal | char[] |
| 数据类型 | 大小 | 说明 | 对应的Java类型 | 对应的C类型 |
|---|---|---|---|---|
| VARCHAR(SIZE) | 0 ~ 65 535字节 | 可变长度字符串 | String | char[] |
| TEXT | 0 ~ 65 535字节 | 长文本数据 | String | char[] |
| MEDIUMTEXT | 0 ~ 16 777 215字节 | 中等长度文本数据 | String | char[] |
| BLOB | 0 ~ 65 535字节 | 二进制形式的长文本数据 | Byte[] | char[] |
VARCHAR(SIZE)所对应的数据所占用的字节数为实际长度加1;
例如:
输入"abcd",用 VARCHAR(3) 存储,则为 “abc” ,4个字节.
| 数据类型 | 大小 | 说明 | 对应的Java类型 | 对应的C类型 |
|---|---|---|---|---|
| DATETIME | 8字节 | (1000-01-01 00:00:00~9999-12-31 23:59:59),不会进行时区的检索和转换 | java.util.Data、java.sql.Timestamp | MYSQL TIME |
| TIMESTAMP | 4字节 | (1970-01-01 00:00:01~2038-01-19 03:14:07),自动检索当前时区进行转换 | java.util.Data、java.sql.Timestamp | MYSQL TIME |
DATETIME 类型用于表示日期和时间,它的显示形式为’YYYY-MM-DD HH: MM:SS’,
其中,YYYY表示年,MM表示月,DD表示日,HH表示小时,MM表示分,SS 表示秒。
TIMESTAMP 类型用于表示日期和时间,它的显示形式与 DATETIME 相同但取值范围比 DATETIME 小。
create database 数据库名称;
成功案例:

错误案例:

show databases;

use 数据库名称;

drop database 数据库名称;

逻辑删除:
操作系统为了方便进行管理,把整个硬盘分成了若干个"盘块";
每个盘块都可以保存一定的数据;
每个文件,实际上可能是由一个或者多个盘快上面的数据来构成的;
当操作系统删除文件的时候,为了提高删除动作的效率,在删除的时候并不是真的把硬盘上之前保存的数据删除掉,而只是把该文件对应的盘块标记为“无效”。
一旦出现误删库的情况,就要尽快让主机断电!!!
这样可以避免操作系统把这些被标记成无效的盘块给分配出去!!!
create table 表名(
字段1 字段类型,
字段2 字段类型,
…
字段n 字段类型
);

show tables;

desc 表名;

drop table 表名;

①所有字段插入数据
insert into 表名 values (值 1,值 2,...);
②指定字段插入数据
(字段名1,字段名2,…):用于指定插人的字段名;
insert into 表名 (字段名1,字段名2,...) values (值 1,值 2,...);
③同时插入多条数据
(值 1,值 2,…),(值 1,值 2,…):表示要插人的数据,以逗号 “ , ” 分割;
insert into 表名 [(字段名1,字段名2,...)]values (值 1,值 2,…),(值 1,值 2,…),...;
①所有字段插入数据

②指定字段插入数据

③同时插入多条数据

select * from 表名;

select 列名1,列名2,... from 表名;

select 表达式 from 表名;
select 表达式 as 别名 from 表名;

select distinct 列名 from 表名;

-- 升序
select 列名 from 表名 order by 列名;
select 列名 from 表名 order by 列名 asc;
-- 降序
select 列名 from 表名 order by 列名 desc;

比较运算符
| 运算符 | 说明 |
|---|---|
| >,>=,<,<= | 大于,大于等于,小于,小于等于 |
| = | 等于,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 个)任意字符;_ 表示任意一个字符 |
逻辑运算符
| 运算符 | 说明 |
|---|---|
| AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
| OR | 任意一个条件为 TRUE(1),结果为 TRUE(1) |
| NOT | 条件为 TRUE(1),结果为 FALSE(0) |
引入 where 字句,针对查询结果进行筛选:
对查询结果进行依次遍历,把对应的查询结果带入到条件中;
条件成立,则把这个记录放到最终查询结果里;反正,则不作为最终结果。
select 列名 from 表名 where 条件;
样本

基本查询

AND 和 OR

范围查询

模糊查询

-- 从 s 开始,筛选 n 条结果
select 列名 from 表名 [where ...] [order by ...] limit n offset s;

update 表名 set 列名 = 值 [, column = expr ...] [where ...] [order by ...] [limit ...]

-- 删除如何条件的行
delete from 表名 where 条件;
-- 删除表中的记录,全删了
delete from 表名;

-- 单行插入
insert into 表(字段1, ..., 字段N) values (value1, ..., value N);
-- 多行插入
insert into 表(字段1, ..., 字段N) values
(value1, ...),
(value2, ...),
(value3, ...);
-- 全列查询
select * from 表
-- 指定列查询
select 字段1,字段2... from 表
-- 查询表达式字段
select 字段1+100,字段2+字段3 from 表
-- 别名
select 字段1 别名1, 字段2 别名2 from 表
-- 去重DISTINCT
select distinct 字段 from 表
-- 排序ORDER BY
select * from 表 order by 排序字段
-- 条件查询WHERE:
-- (1)比较运算符 (2)BETWEEN ... AND ... (3)IN (4)IS NULL (5)LIKE (6)AND (7)OR (8)NOT
select * from 表 where 条件
update 表 set 字段1=value1, 字段2=value2... where 条件
delete from 表 where 条件
数据库可以让程序员定义一些对数据的强制规则,数据库会在插入/修改数据的时候按照这些规则对数据进行校验,如果校验不通过,就直接报错。
约束的本质是让我们及时发现数据中的错误,更好的保证数据的正确性!
字段名 数据类型 NOT NULL;
初始情况下,一个表允许为NULL。

加上 NOT NULL 约束后,就不允许插入空值。

字段名 数据类型 UNIQUE;
初始情况下,表中数据允许重复出现。

加上 UNIQUE 约束后,表中字段的值不能重复出现。

字段名 数据类型 DEFAULT 默认值;
默认的默认值是 NULL,可以通过 default 约束来修改默认值的取值。
对表进行指定列插入的时候,会涉及到默认值;

加上 UNIQUE 约束后,就可以修改默认值。

字段名 数据类型 primary key;
-- 自增主键
字段名 数据类型 primary key auto_increment;
主键表示一条记录的 身份标识,是用来区分这条记录和别的记录的:
MySQL 为了方便大家填写主键,内置了一个功能,“自增主键”,帮助我们自动生成主键的值。
自增主键:
扩展:
如果数据库是分布式部署的,自增主键就要带来问题;
解决思路:分布式唯一 id 生成算法
唯一 id = 时间戳(ms)+ 机房编号/主机编号 + 随机因子(字符串拼接)

自增主键:

外键用于关联其他表的主键或唯一键。
foreign key (字段名) references 主表(列)




check (条件)
create table test_user (
id int,
name varchar(20),
sex varchar(1),
check (sex ='男' or sex='女')
);
根据一些实际的业务场景,来设计表,主要是确定有几个表,每个表的作用是什么,每个表有哪些字段;
一个同学只能有一个账号,一个账户只能分配给一个同学;
方法1:把学生和账号,直接放到一个表里!(下策)
student(id,name,account,password...)
方法2:把学生和账号各自放到一个表里,使用一额外 id 来关联!
-- 1
student(studentid,name,accountid)
account(accountid,password)
-- 2
student(studentid,name)
account(accountid,password,studentid)
一个同学只能属于一个班级,一个班级可以包含多个同学;
方法1
student(id,name)
-- 1 张三
-- 2 李四
-- 3 王五
class(classid,className,studentList)
-- 1 mysql101 1,2
-- 2 mysql102 3
由于 MySQL 中没有 “数组” 这样的类型,所以方法1 是无法实现的。
方法2
class(classid,className)
-- 1 mysql101
-- 2 mysql102
student(id,name,classid)
-- 1 张三 1
-- 2 李四 1
-- 3 王五 2
一个同学可以选择多门课程,一个课程可以包含多个同学;
一般是 采用一个中间表,来表示多对多的关系!
student(studentid,name)
-- 1 张三
-- 2 李四
-- 3 王五
course(courseid,courseName)
-- 1 语文
-- 2 数学
-- 3 英语
student_course(studentid,courseid)
-- 1 1 张三选了语文
-- 1 2 张三选了数学
-- 2 1 李四选了语文
插入查询结果
先执行查询操作,查询出来的结果,插入到另外一个表里。
insert into 表名 select 列名 from 表名;

常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:
| 函数 | 说明 |
|---|---|
| COUNT([DISTINCT] expr) | 返回查询到的数据的 数量 |
| SUM([DISTINCT] expr) | 返回查询到的数据的 总和,不是数字没有意义 |
| AVG([DISTINCT] expr) | 返回查询到的数据的 平均值,不是数字没有意义 |
| MAX([DISTINCT] expr) | 返回查询到的数据的 最大值,不是数字没有意义 |
| MIN([DISTINCT] expr) | 返回查询到的数据的 最小值,不是数字没有意义 |
原表:








select 中使用 group by 子句可以对指定列进行分组查询。
select 列1, sum(列2), ... from 表名 group by 列1,列3;

在进行聚合查询的时候,也能指定条件筛选:
group by 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用 where 语句,而需要用 having;
select 列1, sum(列2), ... from 表名 group by 列1,列3 having 条件;
实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积。
单纯的笛卡尔积,里边包含了大量的无效数据,指定了合理的过滤条件,把有效的数据筛选出来,得到一个有用的数据表。
这个过程,称为 “联合查询”,筛选的条件称为 “连接条件”。
多表查询的一般步骤:
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;
测试数据:
drop table if exists classes;
drop table if exists student;
drop table if exists course;
drop table if exists score;
create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));
create table student (id int primary key auto_increment, sn varchar(20), name varchar(20), qq_mail varchar(20), classes_id int);
create table course (id int primary key auto_increment, name varchar(20));
create table score (score decimal(3,1), student_id int, course_id int);
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');
insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');
insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6);
(1)查询“许仙”同学的 成绩
select stu.name,sco.course_id,sco.score from student stu inner join score sco on stu.id=sco.student_id and stu.name='许仙';
-- 或者
select stu.name,sco.course_id,sco.score from student stu, score sco where stu.id=sco.student_id and stu.name='许 仙';
(2)查询所有同学的总成绩,及同学的个人信息
select stu.name,sum(sco.score) from student stu, score sco where stu.id=sco.student_id group by id;
(3)查询所有同学的成绩,及同学的个人信息
select stu.name, cou.name, sco.score from student stu, course cou, score sco where stu.id = sco.student_id and cou.id = sco.course_id;
外连接分为左外连接和右外连接。
如果联合查询,
-- 左外连接,表1完全显示
select 字段名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 字段名 from 表名1 right join 表名2 on 连接条件;
测试数据1:所连接的表一一对应
drop table if exists student;
drop table if exists score;
create table student (id int, name varchar(20));
create table score (id int, score int);
insert into student values (1, '张三'), (2,'李四'), (3,'王五');
insert into score values (1, 90), (2, 80), (3, 70);
-- 内连接
select name, score from student join score on student.id = score.id;
-- 左外连接
select name, score from student left join score on student.id = score.id;
-- 右外连接
select name, score from student right join score on student.id = score.id;


drop table if exists student;
drop table if exists score;
create table student (id int, name varchar(20));
create table score (id int, score int);
insert into student values (1, '张三'), (2,'李四'), (3,'王五');
insert into score values (1, 90), (2, 80), (4, 70);
-- 内连接
select name, score from student join score on student.id = score.id;
-- 左外连接
select name, score from student left join score on student.id = score.id;
-- 右外连接
select name, score from student right join score on student.id = score.id;


自连接是指在同一张表连接自身进行查询。
一般很少会用到自连接,属于是特殊问题下的特定解决方案;
select 列名 from 表名 as 别名1, 表名 as 别名2 where 条件;
测试数据采用内连接时的数据:
(1)哪个同学的课程1成绩比课程3高;
select s1.student_id from score as s1, score as s2 where s1.student_id = s2.student_id and s1.course_id = 3 and s2.course_id = 1 and s1.score > s2.score;

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询;
单行子查询:返回一行记录的子查询。
查询与“不想毕业” 同学的同班同学:
select name from student where classes_id = (select classes_id from student where name = '不想毕业');

多行子查询:返回多行记录的子查询。
查询“语文”或“英文”课程的成绩信息:
select * from score where course_id in (select id from course where name = '语文' or name = '英文');

select * from score where exists (select score.student_id from course where (name='语文' or name='英文') and course.id = score.course_id);

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用 UNION 和 UNION ALL 时,前后查询的结果集中,字段需要一致。
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
(1)查询id小于3,或者名字为“英文”的课程
select * from course where id < 3 union select * from course where name = '英文';

该操作符用于取得两个结果集的并集。当使用该操作符时,不会自动去掉结果集中的重复行。
(1)查询id小于3,或者名字为“Java”的课程
select * from course where id < 3 union all select * from course where name = 'Java';

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。
要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
show index from 表名;
create index 索引名 on 表名(字段名);
drop index 索引名 on 表名;
准备测试表:
drop table if exists accout;
create table accout(
id int primary key auto_increment,
name varchar(20) comment '账户名称',
money decimal(11,2) comment '金额'
);
insert into accout(name, money) values
('阿里巴巴', 5000),
('四十大盗', 1000);
比如说:四十大盗偷了2000元
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
假如在执行以上第一句SQL时,出现网络错误,或是数据库挂掉了,阿里巴巴的账户会减少2000,但是四十大盗的账户上就没有了增加的金额。
解决方案:使用事务来控制,保证以上两句SQL要么全部执行成功,要么全部执行失败。
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。
(1)开启事务:start transaction;
(2)执行多条SQL语句
(3)回滚或提交:rollback/commit;
说明:rollback即是全部失败,commit即是全部成功。
start transaction;
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
commit;
MySQL基础部分东西还是挺多的,不过都很简单,敲了2w字,总算是结束了,还蛮有成就感的,加油加油!