MySQL学习笔记-恶补基础篇
目录
- 概述
- 1、初识数据库
- 1.1、DataBase
- 1.2、数据库分类
- 1.3、DBMS(数据库管理系统)
- 1.4、命令行操作数据库
- 2、操作数据库
- 2.1、操作数据库
- 2.2、数据库列类型
- 2.3、数据库字段类型
- 2.4、创建数据库表
- 2.5、数据表的类型
- 2.6、修改删除表
- 3、MySQL数据管理
- 3.1、外键
- 3.2、DML语言
- 3.3、添加
- 3.4、修改
- 3.5、删除
- 4、DQL查询数据
- 4.1、DQL
- 4.2、查询
- 4.3、where
- 4.4、联表查询
- 4.5、分页和排序
- 4.6、子查询
- 4.7、分组和过滤
- 5、MySQL函数
- 5.1、常用函数
- 5.2、聚合函数
- 5.3、数据库级别的MD5加密
- 6、事务
- 7、索引
- 7.1、索引的分类
- 7.2、测试索引
- 7.2、索引原则
- 8、权限管理与备份
- 8.1、用户管理
- 8.2、mysql备份
- 9、规范数据库设计
- 9.1、为什么需要设计
- 9.2、数据库三大范式
- 10、JDBC
- 10.1、数据库驱动
- 10.2、JDBC
- 10.3、第一个jdbc程序
- 10.4、statement对象
- 10.5、PreparedStatement对象
- 10.6、事务
- 10.7、数据库连接池
概述
MySQL学习笔记,跟随b站up主狂神,恶补理论,弥补曾经犯下的错误 ,程序员落泪ing…
狂神:只要学不死,就往死里学
视频链接:https://www.bilibili.com/video/BV1NJ411J79W
1、初识数据库
1.1、DataBase
存储数据,管理数据
1.2、数据库分类
关系型数据库
- MySQL ,SQL Server ,DB2 , SQLite…
非关系型数据库:
- Redis
- MongoDB
1.3、DBMS(数据库管理系统)
- 数据库的维护管理软件
1.4、命令行操作数据库
mysql -uroot -p123456 --链接数据库
create database student --创建数据库
show databases; --查看所有数据库
use 数据库名 --切换数据库
show tables -- 查看所有表
describe student --查看student表结构
exit --退出链接
数据库xxx语言:
- DDL 定义
- DML 操作
- DQL 查询
- DCL 控制
2、操作数据库
关键字不区分大小写
2.1、操作数据库
- 创建数据库
create database [if not exists] student
- 使用数据库
--表明或者字段名如果是一个特殊字符,就需要带`
use `student`
- 删除数据库
drop database [if exists] student
2.2、数据库列类型
数值
- tinyint 十分小的数据,1个字节
- smallint 较小的数据 , 2个字节
- mediumint , 3 个字节
- int 标准的整数 , 4个字节
- big 较大的数字,8个字节
- float 单精度浮点数 4 个字节
- double 浮点数 8个字节
- decimal 字符串形式的浮点数 金融计算一般使用decimal
字符串
char 字符串固定大小 0 -255
varchar 可变字符串 0 - 65536
tinytext 微型文本 2^ 8-1
text 文本串 2^ 16 -1 保存大文本
时间日期
- date YYYY-MM-DD 日期格式
- time HH:mm:ss 时间格式
- datetime YYYY-MM-DD HH:mm:ss
- timestamp 时间戳,1970.1.1到现在的毫秒数,也较为常用
- year 年份
null
- 没有值,未知
- 注意不要使用null进行运算
2.3、数据库字段类型
Unsigned
- 无符号整数
- 生命了该列不能声明为负数
zerofill
- 0填充
- 不足的位数使用零填充 int(5) 3 — 003
自增
- 自动在上一条记录的基础上+1
- 通常用来设计唯一的主键,必须是整数类型
- 可以自定义设计主键自增的初始值和步长
非空
- 假设设置为not null,如果不赋值会报错
默认
- 设置默认值
拓展
- 每一个表都要有以下五个字段 ,阿里巴巴开发手册
- id 主键
- version 乐观锁
- is_delete 伪删除
- gmt_create 创建时间
- gmt_update 更新时间
2.4、创建数据库表
create TABLE IF NOT EXISTS `student`(`id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
2.5、数据表的类型
MyISAM和InnoDB的区别
InnoDB 默认使用
MyISAM 早些年使用
MyISAM | InnoDB | |
---|---|---|
事务 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
外键 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
表空间大小 | 较小 | 较大,约为2倍 |
常规使用操作:
- MyISAM 节约空间 速度较快
- InnoDB 安全性高,事务处理,多表多用户操作
在物理空间的位置:
所有数据库文件都存在data文件夹下,本质还是文件存储
- InnoDB : 在数据库表中只有.frm文件,以及上级目录的abdata1文件
- MyISAM对应文件
- frm文件 表结构定义文件
- MYD 数据文件(data)
- MYI 索引文件
2.6、修改删除表
修改
Alter
- 修改表名
Alter Table 旧表名 RENAME as 新表名
- 增加字段
Alter Table 表名 add age Int(11)
- 修改字段(重命名,修改约束)
Alter table 表名 modify age varchar(11) --约束
Alter table 表名 change age age1 varchar(11) --重命名
- 删除表字段
Alter table 表名 drop 字段名
删除
- 删除表
Drop table if exists 表名
所有的创建和删除操作尽量加上判断,以免报错
注意点:
- ``字段名包裹
- 注释 – /**/
- sql大小写不敏感,建议小写
3、MySQL数据管理
3.1、外键
外键居然是了解即可。。。。。
方式一 创建表是增加约束 麻烦
create table `grade`(`id` int(10) not null auto_increment comment 'id',`name` varchar(50) not null comment 'name',primary key (`id`)
)engine=innodb default charset=utf8create TABLE IF NOT EXISTS `student`(`id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',`gradeid` int(10) not null comment '年级',PRIMARY KEY (`id`),key `FK_gradeid`(`gradeid`), --定义外键keyconstraint `FK_gradeid` foreign key(`gradeid`) reference `grade`(`id`) --给这个外键添加约束(执行引用)
)ENGINE=INNODB DEFAULT CHARSET=utf8
删除有外键关系的表,必须先删除引用别人的表(从表),在删除被引用的表(主表)
方法二 修改表添加
alter table `stuent`
add constraint `FK_gradeid` foreign key(`gradeid`) reference `grade`(`id`)
以上都是数据库级别的物理外键,不建议使用(避免数据库过多造成困扰)
最佳实践:
- 数据库就是单纯的表,只用来存数据,只有行和列
- 想用多张表的数据,用程序实现
3.2、DML语言
DML:数据操作语言
3.3、添加
insert
--插入语句
insert into 表名([字段1,字段2,字段3...]) values('值1','值2','值3'...)
--由于主键自增,我们可以省略(如果不写字段,他就会一一匹配)
--我们写插入语句,一定要数据与字段一一对应
--插入多个字段
insert into 表名 ([字段])
values('值1'),('值2'),('值3')...)
注意:
- 字段可以省略,但是后面的值必须一一对应,不能少
3.4、修改
update
update student set name = 'xwy' where id = '1' --没有选择条件默认改变所有数据--修改多个属性
update student set name = 'xwy',email = '11.com' where id = '1'
条件:where子句。运算符 id=某个值,>某个值,在某个区间内修改…
操作符返回布尔值
操作符 | 含义 | 范围 | 结果 |
---|---|---|---|
= | 等于 | 5=6 | false |
<>或者!= | 不等于 | 5<>6 | True |
> , >= | |||
< ,<= | |||
between…and… | 闭合区间 | [2,5] | |
And | |||
or |
注意:
- Column_name 是数据库列,尽量``
- 条件,筛选的条件如果没有指定就会修改所有的列
- value是一个具体的值,也可以是一个变量(时间一般会用)
3.5、删除
delete
delete from 表名 [where 条件]
truncate
完全清空数据库,表的结构和索引约束不会变
truncate table 表名
区别:
- truncate 重新设置自增列,自增会归零!
- truncate不会影响事务
delete删除的问题,重启数据库,现象
- InnoDB 自增列从1开始,存在内存中,断电即失
- MyISAM 继续从上一个自增量开始,存在文件中,不会丢失
4、DQL查询数据
4.1、DQL
- 所有的查询操作都用它 select
- 简单的查询复杂的查询都能用
- 数据库最核心的语言
- 使用频率最高的语言
4.2、查询
select * from student --查询student的全部字段
select stuname from student --查询某个字段
select stuname as 姓名 from student --别名
select concat('姓名:',stuname) as 新名字 from student --函数 拼接字符串
列的名字不是那么见名知意,就用别名
去重查询 distinct
select distinct stuNum from result -- 去除查询结果中重复的数据只显示一条
数据库的列(表达式)
select version() --查询系统版本(函数)
select 100*3 as jieguo --用来计算(计算表达式)
select @@auto_increment_increment --查询自增的步长(变量)
select `studentResult`+1 as '提分后' form result
数据库的表达式:文本值,列,null,函数,计算表达式,系统变量。。。。
4.3、where
作用:检索数据库符合条件的值
逻辑运算符
运算符 | 语法 | 描述 |
---|---|---|
and && | a and b a&&b | 两个都为真就为真 |
or || | a or b a ||b | 一个为真就为真 |
Not ! | not a !a | 真为假,假为真 |
尽量使用英文表达式
select stuNum,sturesult from resultwhere sturesult>=95 and sturesult<=100. --and where sturesult between 95 and 100. --between andwhere sturesult !=1000 --!where not sturesult =1000 --not
模糊查询:比较运算符
运算符 | 语法 | 描述 |
---|---|---|
is null | a is null | 如果操作符为null,结果为真 |
is not null | a is not null | 如果操作符不为null,结果为真 |
between | a beteween b and c | 若a在b和c之间,结果为真 |
like | a like b | sql匹配,如果a匹配b,结果为真 |
in | a in (a1,a2,a3…) | 如果a在a1…中的某一个,结果为真 |
--like结合,%代表0-任意个字符 _代表一个字符
select stuname form student where stuname like '刘%' --姓刘
4.4、联表查询
查询参加了考试的同学的姓名、学号、科目编号、分数
1、分析查询的字段来自那几张表
2、确定使用那种查询? 7种
3、确定交叉点(两个表中哪个数据是是相通的)
select a.studentNo,studendName,SubjectNo,StudentResult
from student as s
inner join result as r
where a.studenNo = r.studentNo
没参加考试的查不出
select a.studentNo,studendName,SubjectNo,StudentResult
from student as s
right join result as r
on s.studentNo = r.studentNo --join on是连接查询 where是等值查询
没参加考试的也查出来
select a.studentNo,studendName,SubjectNo,StudentResult
from student as s
left join result as r
on s.studentNo = r.studentNo
操作 | 描述 |
---|---|
inner join | 如果表中至少有一个匹配,就返回行 |
left join | 即使右表中没有匹配,也会从左表返回所有值 |
Right join | 即使左表中没有匹配,也会从右表返回所有值 |
查询缺考的同学
select a.studentNo,studendName,SubjectNo,StudentResult
from student as s
left join result as r
on s.studentNo = r.studentNo
where studentResult is null
自连接
自己的表和自己的表连接,核心:一张表拆分为两张一样的表
父类
categoryid | pid |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
子类
Pid(父id) | categoryid | categoryName |
---|---|---|
3 | 4 | 数据库 |
2 | 8 | 办公信息 |
3 | 6 | web开发 |
5 | 7 | ps技术 |
操作:查询父类对应的子类关系
select categoryName as '父栏目' ,categoryName as '子栏目'
from category as a ,category as b
on a.categoryid = b.categoryid
4.5、分页和排序
分页 limit、 排序 order by
排序:
select a.studentNo,studendName,SubjectNo,StudentResult
from student as s
left join result as r
on s.studentNo = r.studentNo
order by StudentResult ASC -- 降序 desc
分页:
分页,美页只显示五条数据
select a.studentNo,studendName,SubjectNo,StudentResult
from student as s
left join result as r
on s.studentNo = r.studentNo
order by StudentResult ASC -- 降序 desc
limit 0,5 --limit 起始值,页面大小
4.6、子查询
where(这个值是计算出来的)
本质:在where的语句中嵌套一个子查询语句
--查询数据库结构-1的所有考试结果(学好、科目编号、成绩),降序
--方式1:使用连接查询
select studentNo,r.SubjectNo,studentResult
from result as r
inner jogin subject as sub
on r.subjectNo = sub.subjectNo
where subjectName = '数据库结构-1'
--方式2:子查询(由里及外)
select studentNo,SubjectNo,studentResult
from result
where studentNo = (select studentNo from subject where subjectName = '数据库结构-1')
order by studentResult
4.7、分组和过滤
--查询不同课程的平均分,最高分,最低分,平均分大于80分
select subjectName AVG(studentResult) as 平均分 ,max(StudentResult),Min(StudentResult)
from result r
inner join subject sub
on r.subjectNo = sub.subjectNo
group by r.subjectNo --通过什么子段来分组
having 平均分>80
5、MySQL函数
5.1、常用函数
--数学运算
select ABS(-8) --绝对值
select Ceiling(9.4) --向上取整 10
select Floor(9,4) --向下取整
select Rand() --返回一个0-1之间的随机数
select sign() --判断 一个数的符号,负数返回-1,正数返回1
--字符串函数
select char_length('即使再小的帆也能远航') --字符串长度
select concat('我','爱','你',',们') --拼接字符串
select insert('我爱编程',1,2,'超级爱') --查询,替换 从某个位置开始替换某个长度
select lower('KuangShen')
select upper('KuangShen')
select instr('KuangShen','h') -- 7 返回第一次出现字串的索引
select replace ('坚持就能成功','坚持','努力') --替换出现的字符串
select substr('坚持就能成功',4,6)--源字符串,截取的位置,截取的长度
select reverse('坚持就能成功') --反转
--时间和日期函数
select current_date() --获取当前日期
select now() --获取当前时间
select localtime() -- 获取本地时间
select sysdate() --系统时间
--系统
select system_user() --系统当前登陆用户
select version() --版本
5.2、聚合函数
函数名称 | 描述 |
---|---|
count() | |
sum() | |
avg() | |
max() | |
min() | |
… |
select count(studentName) from student --count(字段) 会忽略null值
select count(*) from student --不会忽略null,本质计算行数
select count(1) from result --不会忽略null,本质计算行数
--!!对于主键字段,用count(字段)更快
--查询不同课程的平均分,最高分,最低分,平均分大于80分
select subjectName AVG(studentResult) as 平均分 ,max(StudentResult),Min(StudentResult)
from result r
inner join subject sub
on r.subjectNo = sub.subjectNo
group by r.subjectNo --通过什么子段来分组
having 平均分>80
5.3、数据库级别的MD5加密
MD5不可逆,具体的值的MD5是一样的
insert into md5Test values(1,'zhangsan',MD5('123456'))
--如何校验:将用户传进来的没密码,进行md5加密,比对加密的值
select * from md5Test where name ='zhangsan' and pwd = MD5('123456')
6、事务
要么都成功,要么都失败
1、A给B转账 A 1000 —>200 B 200
2、B收到A的钱 A 800 --> B 400
将一组SQL放在一个批次中去执行
事务原则ACID
事务的原子性(Atomicity):
是指一个事务要么全部执行,要么不执行,也就是说一个事务不可能只执行了一半就停止了。比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱。不可能划了卡,而钱却没出来。这两步必须同时完成,要么就不完成。
要么都成功,要么都失败
一致性)(Consistency):
是指事务的运行并不改变数据库中数据的一致性。例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变。
事务前后的数据完整性要保持一致,1000
独立性(Isolation):
事务的独立性也称作隔离性,是指两个以上的事务不会出现交错执行的状态。因为这样可能会导致数据不一致,更加具体的来讲,就是事务之间的操作是独立的。
==事务一旦提交则不可逆,被持久化到数据库中!
持久性(Durability):
事务的持久性是指事务执行成功以后,该事务对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚。
==事务的隔离性是多个用户并发访问数据库时,数据库为每一个对象开启的事务,不能被其他事务操作数据库所干预,事务之间要相互隔离。
隔离导致的问题
脏读:
指一个事务读取了另一个事务未提交的数据
不可重复读:
在一个事务内读取表中的某一行数据,多次读取的结果不同。
虚读(幻读):
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致
事务的隔离级别
读未提交(Read Uncommitted)
读未提交,顾名思义,就是可以读到未提交的内容。
因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。
如无特殊情况,基本是不会使用这种隔离级别的。
读提交(Read Committed)
读提交,顾名思义,就是只能读到已经提交了的内容。
这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。这种隔离级别能够有效的避免脏读,但除非在查询中显示的加锁,如:
select * from T where ID=2 lock in share mode;
select * from T where ID=2 for update;
不然,普通的查询是不会加锁的。
那为什么“读提交”同“读未提交”一样,都没有查询加锁,但是却能够避免脏读呢?
这就要说道另一个机制“快照(snapshot)”,而这种既能保证一致性又不加锁的读也被称为“快照读(Snapshot Read)”
假设没有“快照读”,那么当一个更新的事务没有提交时,另一个对更新数据进行查询的事务会因为无法查询而被阻塞,这种情况下,并发能力就相当的差。
而“快照读”就可以完成高并发的查询,不过,“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。
可重复读(Repeated Read)
可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。
在这个级别下,普通的查询同样是使用的“快照读”,但是,和“读提交”不同的是,当事务启动时,就不允许进行“修改操作(Update)”了,而“不可重复读”恰恰是因为两次读取之间进行了数据的修改,因此,“可重复读”能够有效的避免“不可重复读”,但却避免不了“幻读”,因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。
串行化(Serializable)
这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。
这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。
--mysql默认开启事务自动提交--手动处理事务
SET autocommit = 0 --关闭事务
--事务开启
start transaction --标记一个事务的开始,从这个之后的sql都在同一个事务里--提交:持久化(成功)
commit
--回滚:回到原来的样子(失败)
rollback
--事务结束
set autocommit = 1--了解
savepoint 保存点名字--保存点
rollback to savepoint 保存点名字--回滚到保存袋内
release savepoint 保存点名字 --撤销保存点
模拟场景
--转账
create database shop character set utf8 collate utf8_general_ci
use shop
--创建数据库
...
--插入数据
INSERT INTO account(name,money)
VALUES('A',2000.00),('B',10000.00)--开启事务
set autocommit = 0;
start TRANSACTION
update account set Money = money-500 where name='A';
update account set Money = money+500 where name='B';
COMMIT;
set autocommit=1;
7、索引
索引是帮助mysql高效获取数据的数据结构
7.1、索引的分类
- 主键索引 primary key
- 唯一的标识,不可重复,只能有一个列作为主键
- 唯一索引 unique key
- 避免重复列出现,唯一索引可以重复,多个列都可以标识为唯一索引
- 常规索引 key/index
- 默认的,index/key关键字设置
- 全文索引 FullText
- 在特定的数据库引擎下才有,MyISAM
- 快速定位数据
--索引的使用
--1、在创建表的时候给字段增加索引
--2、创建完毕后,增加索引--显示所有的索引信息
show index from student
--增加一个索引
alter table student add fulltext index studentName(studentName) -- 索引名(列名)
--分析sql执行的状况
explain select * from student --非全文索引
explain select * from student where match(studentName) against('刘') --全文索引
7.2、测试索引
--sql编程,了解就行
--插入一万条数据
delimiter $$ --写函数之前必须要写,标志
create function mock_data()
returns int
begindeclare num int default 1000000;declare i int defalut 0;where i <num doinsert into app_user(name,email,phone,gender,password,age) values(concat('用户',i),'123456@qq.com'............);set i = i+1;end while;return i;
end;select mock_data();--使用索引
select * from app_user where name = '用户9999'; --要转个圈 耗时接近一秒钟
--id_表名_字段名
--create index 索引名 on 表名(字段)
create index id_app_user_name on app_user(name);
select * from app_user where name = '用户9999'; --耗时0.001
索引在小数据量的时候用处不大,在大数据时,区别十分明显
7.2、索引原则
- 索引不是越多越好
- 不要对经常变动的数据加索引
- 小数据量表不需要加索引
- 索引一般应该加在常用来查询的字段上
索引的数据结构
Hash类型的索引
BTree:InnoDB的默认数据结构
8、权限管理与备份
8.1、用户管理
sql命令
用户表:mysql下的user表
本质:对这张表进行增删改查
--创建用户
create user kuangshen identified by '123456'
--修改密码(当前登陆)
set password = password('111111')
--修改密码(其他用户)
set password for kuangshen = password('111111')
--重命名
rename user kuangshen to xxx
--用户授权 全部权限 库.表
--all privileges 除了给别人授权(grant),其余的都可以干
grant all privileges on *.* to xxx
--查询权限
show grants for xxx --执行用户
show grants for root@localhost --root用户权限
--撤销权限
revoke all privileges on *.* from xxx
--删除用户
drop user xxx
8.2、mysql备份
- 保证重要的数据不丢失
- 数据转移
MySQL数据库备份方式:
- 直接拷贝物理文件
- 可视化工具中手动倒出
- 选择备份或导出,一般选择结构+数据
- 使用命令行倒出 mysqldump
mysqldump -hlocalhost -uroot -p123456 school student result >D:/a.sql
--导入
--登陆的情况下,切换到指定的数据库
source 备份文件
假设要备份数据库,以防数据丢失
把数据库给朋友!sql给别人即可!
9、规范数据库设计
9.1、为什么需要设计
当数据库比较复杂的时候,就需要设计
糟糕的数据库设计:
- 数据冗余,浪费空间
- 数据库插入和删除都会麻烦,异常【屏蔽使用物理外键】
- 程序性能差
良好的数据库设计:
- 节省内存空间
- 保证数据库完整性
- 方便我们开发系统
软件开发中关于数据库的设计:
- 分析需求,分析业务和需要处理数据库的需求
- 概要设计:设计关系图E-R图
设计数据库的步骤(个人博客)
- 收集信息,分析需求
- 用户表(用户登录注销,用户的个人信息,写博客,创建分类)
- 分类表(文章分类,谁创建的)
- 文章表(文章信息)
- 友链表
- 自定义表(系统信息,某个关键的字,或者一些主字段 key:value
- 标识实体(把需求落实到每个字段)
- 标识实体之间的关系
- 写博客 user->blog
- 分类 User->category
- 关注 User->user
- 友链 links
- 评论 User->user
9.2、数据库三大范式
- 信息重复
- 更新异常
- 插入异常
- 无法正常显示信息
- 删除异常
- 丢失有效信息
三大范式
第一范式(1NF):要求数据库表的每一列都是不可分割的原子数据项。
保证每一列不可分
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)
第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。
每张表只描述一件事情
第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
每一列都和主键直接相关,而不能间接相关
规范性和性能的问题
关联查询的表不能超过三张表
- 考虑商业化的需求和目标(成本、用户体验)数据库的性能更加重要
- 在规范性的问题的时候,需要适当考虑一下规范性
- 故意给某些表增加一些冗余字段
- 故意增加一些计算列(从大数据量减为小数据量的查询)
10、JDBC
10.1、数据库驱动
我们的程序通过数据库驱动和数据库打交道!
10.2、JDBC
简化开发人员对数据库统一操作,提供java操作数据库的规范,俗称jdbc
规范的实现由具体厂商去做
对于开发人员只需要掌握jdbc接口即可
10.3、第一个jdbc程序
1、创建项目
2、导入jar包
3、编写测试代码
package com.xxx;import java.sql.*;/*** @author levi* @create 2020/9/7 6:37 下午*/
public class JDBCFirstDemo {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1、 加载驱动Class.forName("com.mysql.jdbc.Driver");//2、用户信息和urlString url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8";String username = "root";String password = "123456";//3 连接成功,数据库对象Connection connection = DriverManager.getConnection(url,username,password);//4 执行sql的对象Statement statement = connection.createStatement();//5、执行sql对象去执行sql,可能返回结构,查看返回结果String sql = "select * from account";ResultSet resultSet = statement.executeQuery(sql);//结果集包含所有查询出的结果while(resultSet.next()){System.out.println("id="+resultSet.getObject("id"));System.out.println("name="+resultSet.getObject("name"));System.out.println("money="+resultSet.getObject("money"));}//6、释放链接resultSet.close();statement.close();connection.close();}
}
DriverManager
Class.forName("com.mysql.jdbc.Driver"); //固定写法
Connection connection = DriverManager.getConnection(url,username,password);//connection 代表数据库
connect.commit();
connect.rollback();
connect.setAutoCommit();
URL
协议://ip:端口/数据库名?参数1&参数2&参数3
//oracle --1521
//jdbc:oracle:thin:@localhost:1521:sid
statement执行sql的对象
statement.executeQuery(); //查询返回ResultSet
statement.execute(); //执行任何sql
statement.executeUpdate(); //更新、插入、删除都用这个,返回一个受影响的行数
ResultSet 查询结果集,封装所有查询结果
获取指定数据类型
resultSet.getObject(); //不知道列类型时使用
resultSet.getString();
resultSet.getInt();
.....
遍历
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后
resultSet.next();//移动到下一个
resultSet.previous(); //移动到前一个
resultSet.absolute(row);//移动到指定行
释放链接
resultSet.close();
statement.close();
connection.close();
10.4、statement对象
配置累
driver = com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
username=root
password=123456
提取工具类
package com.xxx;import java.sql.*;/*** @author levi* @create 2020/9/7 6:37 下午*/
public class JDBCFirstDemo {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1、 加载驱动Class.forName("com.mysql.jdbc.Driver");//2、用户信息和urlString url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8";String username = "root";String password = "123456";//3 连接成功,数据库对象Connection connection = DriverManager.getConnection(url,username,password);//4 执行sql的对象Statement statement = connection.createStatement();//5、执行sql对象去执行sql,可能返回结构,查看返回结果String sql = "select * from account";ResultSet resultSet = statement.executeQuery(sql);//结果集包含所有查询出的结果while(resultSet.next()){System.out.println("id="+resultSet.getObject("id"));System.out.println("name="+resultSet.getObject("name"));System.out.println("money="+resultSet.getObject("money"));}//6、释放链接resultSet.close();statement.close();connection.close();}
}
测试插入
package com.xwy;import com.xwy.util.JDBCUntil;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;/*** @author levi* @create 2020/9/7 7:24 下午*/
public class Test {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try{connection = JDBCUntil.getConnect();statement = connection.createStatement();String sql = "insert into account(name,money) values('xxx',1000.00)";int i = statement.executeUpdate(sql);if(i>0){System.out.println("插入成功");}}catch (SQLException e){e.printStackTrace();}finally {JDBCUntil.relase(connection,statement,resultSet);}}
}
SQL注入问题
sql存在漏洞会被攻击导致泄漏
本质:sql会被拼接
10.5、PreparedStatement对象
防止sql注入,效率更高
package com.lesson03;import com.xwy.util.JDBCUntil;import java.math.BigDecimal;
import java.sql.*;/*** @author levi* @create 2020/9/7 7:38 下午*/
public class Test {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = JDBCUntil.getConnect();String sql = "insert into account(name,money) values(?,?)";//预编译//防止sql注入的本质,将传递过来的参数当作字符// 假设存在转义字符,直接忽略掉 ' 会被直接转义掉statement = connection.prepareStatement(sql);statement.setString(1,"xwy");BigDecimal bigDecimal = new BigDecimal("13304.00");statement.setBigDecimal(2, bigDecimal);int i = statement.executeUpdate();if(i>0){System.out.println("插入成功");}}catch (SQLException e){e.printStackTrace();}finally {JDBCUntil.relase(connection,statement,null);}}
}
10.6、事务
package com.lesson04;import com.xwy.util.JDBCUntil;import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @author levi* @create 2020/9/7 8:29 下午*/
public class TestTransaction {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = JDBCUntil.getConnect();connection.setAutoCommit(false);String sql1 = "update account set money = money-100 where name = 'A'";statement = connection.prepareStatement(sql1);statement.executeUpdate();String sql2 = "update account set money = money+100 where name = 'B'";statement = connection.prepareStatement(sql2);statement.executeUpdate();connection.commit();System.out.println("操作成功");}catch (SQLException e){try{connection.rollback();}catch (SQLException e1){e1.printStackTrace();}e.printStackTrace();}finally {JDBCUntil.relase(connection,statement,resultSet);}}
}
10.7、数据库连接池
数据库连接释放十分浪费资源
池化技术:准备一些预先的资源,过来就链接预先准备好的
最小连接数:常用连接数
最大连接数:业务最高承载上限
排队等待
等待超时:100ms
编写连接池,实现接口DataSource
开源数据源实现
DBCP
C3P0
Druid:阿里巴巴
使用数据库连接池,就不需要再编写连接数据库的代码了
DBCP
需要用到jar包
commons-dbcp-1.4.jar
Commons-pool-1.6.jar
工具类
package com.lesson05.utils;import com.xwy.util.JDBCUntil;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*** @author levi* @create 2020/9/7 10:44 下午*/
public class JDBCUtils_DBCP {private static DataSource dataSource = null;static {try{InputStream in = JDBCUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");Properties properties = new Properties();properties.load(in);//创建数据源dataSource = BasicDataSourceFactory.createDataSource(properties);}catch (Exception e){e.printStackTrace();}}//获取链接public static Connection getConnect() throws SQLException {return dataSource.getConnection();//从数据源获取连接}//释放链接public static void relase(Connection connection , Statement statement, ResultSet resultSet){if(resultSet!=null){try{resultSet.close();}catch (SQLException e){e.printStackTrace();}}if(statement!=null){try{statement.close();}catch (SQLException e){e.printStackTrace();}}if(connection!=null){try{connection.close();}catch (SQLException e){e.printStackTrace();}}}
}
测试代码
package com.lesson05;import com.lesson05.utils.JDBCUtils_DBCP;
import com.xwy.util.JDBCUntil;import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @author levi* @create 2020/9/7 10:54 下午*/
public class TestDBCP {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = JDBCUtils_DBCP.getConnect();String sql = "insert into account(name,money) values(?,?)";//预编译//防止sql注入的本质,将传递过来的参数当作字符// 假设存在转义字符,直接忽略掉 ' 会被直接转义掉statement = connection.prepareStatement(sql);statement.setString(1,"lll");BigDecimal bigDecimal = new BigDecimal("13304.00");statement.setBigDecimal(2, bigDecimal);int i = statement.executeUpdate();if(i>0){System.out.println("插入成功");}}catch (SQLException e){e.printStackTrace();}finally {JDBCUtils_DBCP.relase(connection,statement,null);}}
}
CP30
xml配置
…
结论:无论使用什么数据源,本质是一样的,DataSource接口不会变
MySQL学习笔记-恶补基础篇相关推荐
- 菜鸟学习笔记:Java基础篇7(包装类、时间相关类、文件类、异常处理类)
菜鸟学习笔记:Java其他常用类 基本数据类型包装类 时间处理和文件处理相关类 Date时间类 SimpleDateFormat Calendar日历类 文件类 异常机制 异常的概念 Java异常处理 ...
- 菜鸟学习笔记:Java基础篇6(数组、字符串)
菜鸟学习笔记:Java常用类(数组.字符串) 数组 概述 数组的定义 二维数组 数组查找和排序 查找 排序 数组运用--字符串 不可变字符序列(String) 可变字符序列(StringBuilder ...
- 菜鸟学习笔记:Java基础篇5(抽象类与接口、回调函数、内部类)
菜鸟学习笔记:Java面向对象篇下 抽象类 接口 回调函数 内部类 成员内部类 匿名内部类 抽象类 通过前面知识的学习,抽象类这个概念应该不难理解,但比较容易和后面要说的接口混淆,而且在面试中也比较爱 ...
- 菜鸟学习笔记:Java基础篇4(面向对象三大特征)
菜鸟学习笔记:Java面向对象篇中 继承 概念 方法重写(override) Object类 Super关键字 组合 final关键字补充 封装 访问控制符 多态 继承 概念 继续上一篇的例子: #m ...
- 菜鸟学习笔记:Java基础篇3(面向对象思想、程序执行过程内存分析、面向对象重要概念)
菜鸟学习笔记:Java面向对象篇上 Java面向对象的思想 Java程序执行过程内存分析 Java垃圾回收机制 构造方法 方法重载(overload) static关键字 this关键字 Java面向 ...
- 菜鸟学习笔记:Java基础篇2(变量、运算符、流程控制语句、方法)
菜鸟学习笔记:Java基础篇2 变量 基本概念 变量作用域 final关键字 运算符 算术运算符 比较运算符 逻辑运算符 位运算符 赋值运算符 条件运算符 运算符优先级 Java三种流程控制语句 顺序 ...
- MySQL学习笔记一之基础架构
MySQL学习笔记一之架构@TOC 架构图如下 Server层 连接器 负责跟客户端建立连接.获取权限.维持和管理连接 客户端如果太长时间没有动静,连接器会将其自动断开,时间由参数wait_timeo ...
- MySQL学习笔记_8_SQL语言基础复习
SQL语言基础复习 一.概述 SQL语句注释方式 1)以"#"开头直到行尾的所有内容都是注释 2)以"--"(--后还有一个空格)开头直到行尾的所有内容都是注释 ...
- 【网络安全态势感知学习笔记】——“行远自迩”基础篇一:网络安全态势感知的基本概念
文章目录 1. 网络安全态势感知的基本概念 1.1 态势感知的基本概念 1.2 网络安全态势感知 1.2.1 网络安全态势感知的定义 1.2.2 网络安全态势感知的阶段 1.2.3 网络安全态势感知的 ...
最新文章
- 悔不当初:回顾进化之路
- [转]关于WM_NCHITTEST消息
- C#nbsp;Listlt;gt;简单用法
- 将控制台输出重定向到textbox的dotnet类
- Google推荐的15条军规:HTML5代码规范
- python程序设计陈春晖答案_Python程序设计
- 华成英模拟电子技术笔记(1)-绪
- 微信小程序Animation动画的使用
- springcloud五大组件永远滴神——成神之路
- python基础----Day06
- 楚门的世界/The Truman Show (1998)
- Andromeda 源码解析 (同步获取服务)
- note3+android+5.1,最新的安卓5.1.1 ROOT教程(不需要刷第三方内核)
- (Tekla Structures二次开发)自动标注尺寸展示
- 全国省份GDP动态统计图表echarts.js插件
- 计算机电脑无法充电,iphone连接电脑无法充电怎么办
- 第14届蓝桥杯STEMA测评真题剖析-2022年11月27日Scratch编程初中级组
- 声波正演c语言程序,二维频率域声波方程正演模拟
- B1094 谷歌的招聘 (20 分)
- 六年级下册计算机电子板报教案,六年级下信息技术教案电子报刊设计河大版.doc...