MySQL 学习
1. 数据库的分类
1.1 关系型数据库:
- MySQL、Oracle等
- 通过表与表、行与列的关系进行存储数据。
1.2 非关系型数据库:
- Radis等
- 通过存储对象来存储数据,数据由对象的属性决定。
2. 操作数据库
操作数据库 —> 操作数据库中的表 —> 操作数据库中表的数据
2.1 操作数据库
- 创建数据库
- creat database [if not exists] testdatabase;
复制代码
- 删除数据库
- drop database [if exists] testdatabase;
复制代码
- 使用数据库
- -- 如果表名或字段名是特殊字符,则需要带上``
- use `testdatabase`;
复制代码
- 查看数据库
2.2 创建数据库的表
- create table if not exists `test_table01`(
- `id` int(4) not null auto_increment comment '学号',
- `name` varchar(30) not null default '匿名' comment '姓名',
- `pwd` varchar(20) not null default '123456' comment '密码',
- `sex` varchar(2) not null default '男' comment '性别',
- `birthday` datetime default null comment '出生日期',
- `address` varchar(100) default null comment '家庭住址',
- `email` varchar(50) default null comment '邮箱',
- primary key(id)
- )engine=innodb default charset=utf8
复制代码 2.3 数据表的类型
- /*
- INNODB 默认使用
- MYISAM 早些年使用
- */
复制代码 MYISAMINNODB事务支持不支持支持数据行锁定不支持支持外键约束不支持支持全文索引支持不支持表空间的大小较小较大,约为2倍各自的优点:
- MYISAM: 节约空间,速度较快
- INNODB: 安全性高,事务的处理,多表多用户操作
2.4 修改删除表
修改表
- -- 修改表的各种操作
- -- 1.修改表的表名 公式: alter table 旧表名 rename as 新表名;
- alter table `test_table01` rename as `test_table`;
- -- 2.增加表的字段 公式: alter table 表名 add 字段名 数据类型 [默认 注释];
- alter table `test_table` add age02 int(2) default 18 comment '年龄';
- -- 3.修改表的字段 公式: alter table 表名 modify 旧字段名 新数据类型;
- -- MODIFY只能改数据类型和约束; 公式: alter table 表名 change 旧字段名 新字段名 新数据类型;
- -- CHANGE可以重命名以及数据类型和约束,但必须重命名后才能改数据类型和约束。
- alter table `test_table` MODIFY age VARCHAR(2);
- alter table `test_table` CHANGE age02 age int(2);
- alter table `test_table` CHANGE age age01 VARCHAR(2);
- -- 4.删除表的字段 公式: alter table 表名 drop 旧字段名;
- alter table `test_table` DROP age01
复制代码删除表
- -- 删除表的操作
- -- 公式: drop table [if exists] `表名`;
- drop table if exists `test_table`;
复制代码 3. MySQL 数据管理
3.1 外键
MySQL可以在创建表时或者修改表时添加物理外键,数据库级别的外键,但不建议使用(避免数据库国多造成困扰)。
最佳实践
- 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)。
- 当想要使用多张表的数据,使用外键时,通过程序来实现外键。
3.2 DML 语言(全部记住)
插入(insert)
- -- 插入字段操作
- -- 公式:insert into `表名` (`字段一`,`字段二`,....) values ('数据一','数据二',....);
- insert into `test_table` (`name`,`pwd`) values ('小王','123654');
- -- 插入多条字段
- insert into `test_table` (`name`,`pwd`) values ('小红','789654'),('小白','132146');
复制代码修改(update)
- -- 修改字段操作
- -- 公式:update `表名` set `字段名一` = '新的值'[, `字段名二` = '新的值',...] where [条件];
- update `test_table` set `name` = '老王' where `name` = '老王';
- -- 修改多个字段
- update `test_table` set `name` = '老王',`pwd` = '987465' where `name` = '小王';
复制代码 注意:
<ul>合理运用条件中的 =,!=,>,=,= 60 and `studentresult` = 60 && `studentresult` 60[/code]模糊查询(比较运算符)
- -- 删除字段操作
- -- 公式:1.delete from `表名` where [条件]
- -- 2.truncate table `表名`
- delete from `test_table` where `name` = '小白';
- truncate table `test_table`;
复制代码 4.3 联表查询
join对比
- select [all | distinct]
- {* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]}
- from table_name [as table_alias]
- [left | right | inner join table_name2] -- 联合查询
- [where ...] -- 指定结果需满足的条件
- [group by ...] -- 指定结果按照哪几个字段来分组
- [having] -- 过滤分组的记录必须满足的次要条件
- [order by ...] -- 指定查询记录按一个或多个条件排序
- [limit {[offset,]row_count | row_countOFFSET offset}];
- -- 指定查询的记录从哪条到哪条
复制代码 操作描述inner join如果两个表种至少有一个匹配,就返回行left join会把left左边的表作为主表,返回左表所有的值,即使右表中没有匹配right join会把right右边的表作为主表,返回右表所有的值,即使左表中没有匹配自连接
- -- 查询全部的学生
- -- 公式:select 字段 from `表名`;
- SELECT * FROM `student`;
- -- 查询指定字段
- select `studentno`, `studentname` from `student`;
- -- as用来起别名,字段和表名都可以
- select `studentno` as 学号, `studentname` as 姓名 from `student`;
- -- 拼接函数concat(a,b)
- select CONCAT('学号:',`studentno`,',姓名:',`studentname`) as 信息 from `student`;
复制代码 4.4 分页和排序
排序(order by)
- -- 查询哪些学生参加了考试
- select * from `result`; -- 查询全部成绩
- select `studentno` from `result`; -- 查询有哪些学生参加考试
- -- 数据有重复,需要去重
- select distinct `studentno` from `result`;
复制代码分页(limit)
- -- 学员成绩+1分
- select `studentno` as 学号, `studentresult` + 1 As 新成绩 from `result`;
复制代码 4.5 子查询
- -- ========================================== where子句 ==============================================
- select `studentno` , `studentresult` from `result`;
- -- 查询成绩在60-100的学生
- select `studentno`, `studentresult` from `result`
- where `studentresult` >= 60 and `studentresult` <= 100;
- -- &&表达式
- select `studentno`, `studentresult` from `result`
- where `studentresult` >= 60 && `studentresult` <= 100;
- -- between...and 表达式
- select `studentno`, `studentresult` from `result`
- where `studentresult` between 60 and 100;
- -- not 表达式
- select `studentno`, `studentresult` from `result`
- where not `studentresult` > 60
复制代码 4.7 分组和过滤
- -- %代表0-任意个字符,_代表一个字符,只能用于like中
- -- 查询所有姓张的学生
- select * from `student`
- where `studentname` like '张%';
- -- 查询姓张的两个字的学生
- select * from `student`
- where `studentname` like '张_';
- -- 查询姓张的三个字的学生
- select * from `student`
- where `studentname` like '张__';
- -- 查询名字里带张的学生
- select * from `student`
- where `studentname` like '%张%';
- -- 查询名字中间带张的学生
- select * from `student`
- where `studentname` like '_%张%';
- -- ============================== in =============================================
- -- 查询学号在1000,1001,1002的学生
- select * from `student`
- where `studentno` in(1000,1001,1002);
- -- 查询地址在北京朝阳、广东深圳的学生
- select * from `student`
- where `address` in('北京朝阳','广东深圳');
- -- ============================== null / not null =============================================
- -- 查询电话号码为空的学生
- select * from `student`
- where `phone` = '';
- -- 查询电话号码不为空的学生
- select * from `student`
- where `phone` is not null;
复制代码 5. MySQL函数
5.1 聚合函数
函数描述count()计数sum()求和avg()平均值max()最大值min()最小值- -- ========================================= 联表查询 =============================================
- /* 思路:
- 1. 分析需求,分析查询的字段来自哪些表
- 2. 确定使用哪种连接查询?7种
- 3. 确定交叉点(这两个表哪些数据是相同的)
- */
- -- 查询参加了考试的学生(学号、姓名、科目编号、分数)
- select * from `student`;
- select * from `result`;
- -- inner join
- select s.studentno,studentname,subjectno,studentresult
- from result as r
- inner join student as s
- on s.studentno = r.studentno;
- -- right join 结果多了没参加考试的学生
- select s.studentno,studentname,subjectno,studentresult
- from result as r
- right join student as s
- on s.studentno = r.studentno;
- -- right join 把左右两边的表调换试试,结果只有参加了考试的学生,因此,left左边的表都展示,right右边的表都展示
- select s.studentno,studentname,subjectno,studentresult
- from student as s
- right join result as r
- on s.studentno = r.studentno;
- -- left join 结果和inner join一样,都是参加了考试的学生
- select s.studentno,studentname,subjectno,studentresult
- from result as r
- left join student as s
- on s.studentno = r.studentno;
- -- left join 把左右两边的表调换试试,结果多了没参加考试的学生,因此,left左边的表都展示,right右边的表都展示
- select s.studentno,studentname,subjectno,studentresult
- from student as s
- left join result as r
- on s.studentno = r.studentno;
- -- 查询缺考的同学
- select s.studentno,studentname,subjectno,studentresult
- from student as s
- left join result as r
- on s.studentno = r.studentno
- where studentresult is null;
- -- 查询学生所属的年纪(学号、姓名、年纪名称)
- select studentno,studentname,gradename
- from student as s
- left join grade as g
- on s.gradeid = g.gradeid;
- -- 查询科目所属的年纪(科目名称,年纪名称)
- select subjectname,gradename
- from grade as g
- inner join subject as s
- on g.gradeid = s.gradeid;
- -- 思考题:查询参加考试同学的信息:学号、姓名、科目名、分数
- select s.studentno,studentname,subjectname,studentresult
- from result as r
- left join student as s
- on s.studentno = r.studentno
- left join `subject` as k
- on r.subjectno = k.subjectno
- -- 思考题:查询参加 数据库结构-1 考试同学的信息:学号、姓名、科目名、分数
- select s.studentno,studentname,subjectname,studentresult
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- inner join `subject` as sub
- on sub.subjectno = r.subjectno
- where sub.subjectname = '数据库结构-1';
复制代码 5.2 数据库级别的MD5加密(扩展)
- -- ============================== 自连接 =============================================
- -- 查询父子信息
- select f.categoryName as '父栏目',z.categoryName as '子栏目'
- from category as f, category as z
- where f.categoryid = z.pid;
复制代码 6. 事务⭐
事务原则:ACID原则 原子性、一致性、隔离性、持久性
参考链接:(https://blog.csdn.net/dengjili/article/details/82468576/)
要么都成功,要么都失败
事务前后的数据完整性要保持一致
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务 的操作数据所干扰,多个并发事务之间要相互隔离。
事务一旦提交则不可逆,被持久化到数据库中
隔离所导致的一些问题
指一个事务读取了另外一个事务未提交的数据。
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合 不对)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致。
执行事务
- -- 排序的公式: order by 通过哪个字段排序 怎么排(asc升序,desc降序)
- -- 查询的结果根据成绩排序
- select s.studentno,studentname,subjectname,studentresult
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- inner join `subject` as sub
- on sub.subjectno = r.subjectno
- where sub.subjectname = '数据库结构-1'
- order by studentresult asc;
复制代码模拟场景
- -- 分页的公式: limit 起始值,页面大小
- -- 第一页: limit 0,5 (1-1)*5
- -- 第二页: limit 5,5 (2-1)*5
- -- 第三页: limit 10,5 (3-1)*5
- -- 第四页: limit 15,5 (4-1)*5
- -- 第N页: limit (n-1)*5,5 (n-1)*pagesize,pagesize
- -- [pagesize:页面大小]
- -- [(n-1)*pagesize:起始值]
- -- [n:当前页]
- -- [数据总数 / 页面大小 = 总页数]
- -- 对排序的结果进行分页
- select s.studentno,studentname,subjectname,studentresult
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- inner join `subject` as sub
- on sub.subjectno = r.subjectno
- order by studentresult asc
- limit 0,5;
- -- 查询 java第一学年 课程成绩排名前十的学生,并且分数要大于80的学生信息(学号、姓名、课程名称、分数)
- select s.studentno,studentname,subjectname,studentresult
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- inner join `subject` as sub
- on sub.subjectno = r.subjectno
- where r.studentresult > 80 and sub.subjectname = 'Java程序设计-1'
- order by r.studentresult desc
- limit 0,10;
复制代码 7. 索引
MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构。索引是数据结构。
7.1 索引的分类
在一个表中,主键索引只能有一个,唯一索引可以有多个
- 主键索引(primary key)
- 唯一索引(unique key)
- 常规索引(key / index)
- 全文索引(FullText)
- 在特定的数据库引擎下才有,MYISAM
- 快速定位数据
参考链接:https://blog.csdn.net/jiadajing267/article/details/81269067
基础语法
- -- =========================================== where子查询 =============================================
- -- 1.查询数据库结构-1 的所有考试结果(学号、名字、成绩)降序排序
- -- 方式一:连接查询
- select s.studentno,studentname,studentresult
- from result as r
- inner join `student` as s
- on r.studentno = s.studentno
- inner join `subject` as sub
- on r.subjectno = sub.subjectno
- where sub.subjectname = '数据库结构-1'
- order by studentresult desc
- -- 方式二:子查询
- select s.studentno,studentname,studentresult
- from result as r
- inner join student as s
- on r.studentno = s.studentno
- where subjectno = (
- select subjectno
- from `subject`
- where subjectname = '数据库结构-1'
- )
- order by studentresult desc
- -- 分数不小于80分的学生的学号和姓名
- -- 方式一:连接查询
- select distinct s.studentno,studentname
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- where studentresult >= 80
- -- 方式二:子查询
- select studentno,studentname
- from student
- where studentno in (
- select studentno
- from result
- where studentresult >= 80
- )
- -- 在这个基础上加个科目,高等数学-2
- -- 方式一:
- select s.studentno,studentname
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- inner join `subject` as sub
- on sub.subjectno = r.subjectno
- where subjectname = '高等数学-2' and studentresult >= 80
- -- 方式二:
- select studentno,studentname
- from student
- where studentno in (
- select studentno
- from result as r
- inner join `subject` as sub
- on r.subjectno = sub.subjectno
- where subjectname = '高等数学-2' and studentresult >= 80
- )
- -- 方式三:(虽然阅读成本高,但效率要高于联表查询)
- select studentno,studentname
- from student
- where studentno in (
- select studentno
- from result
- where subjectno = (
- select subjectno
- from `subject`
- where subjectname = '高等数学-2'
- ) and studentresult >= 80
- )
- -- 查询c语言-1 前五名学生的信息(学号,姓名,成绩)
- -- 方式一: 联表查询
- select s.studentno,studentname,studentresult
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- inner join `subject` as sub
- on sub.subjectno = r.subjectno
- where subjectname = 'C语言-1'
- order by studentresult desc
- limit 0,5
- -- 方式二:子查询
- select s.studentno,studentname,studentresult
- from student as s
- inner join result as r
- on s.studentno = r.studentno
- where subjectno = (
- select subjectno
- from `subject`
- where subjectname = 'C语言-1'
- )
- order by studentresult desc
- limit 0,5
复制代码 7.2 测试索引
- -- 查询不同课程的平均分,最高分,最低分,并且平均分要高于80
- -- 核心:根据不同学科分组
- select subjectname,avg(studentresult) as 平均分,max(studentresult) as 最高分,min(studentresult) as 最低分
- from result as r
- inner join `subject` as sub
- on r.subjectno = sub.subjectno
- group by r.subjectno
- having 平均分 >= 80
复制代码CRUD操作-delete
- -- =========================================== 聚合函数 =============================================
- -- count(字段) 会忽略所有的null值
- -- count(*) 不会忽略null值,本质是计算行数
- -- count(1) 不会忽略null值,本质是计算行数
- -- 对于有主键的时候,用count(字段)效率要高于count(1),否则count(1)效率高,即count(主键列)>count(1)>count(非主键列)
- select count(studentname) from student;
- select count(*) from student;
- select count(1) from student;
- select sum(studentresult) as 总分 from result;
- select avg(studentresult) as 平均分 from result;
- select max(studentresult) as 最高分 from result;
- select min(studentresult) as 最低分 from result;
复制代码CRUD操作-update
- -- =========================================== 测试MD5加密 =============================================
- create table `testmd5`(
- `id` int(4) not null,
- `name` varchar(20) not null,
- `pwd` varchar(50) not null,
- primary key(`id`)
- )engine = innodb default charset = utf8
- -- 明文密码
- insert into `testmd5`(`id`,`name`,`pwd`)
- values('1','张三','132456'),
- ('2','李四','564123'),
- ('3','王五','456784'),
- ('4','赵六','213456'),
- ('5','小王','789546')
- -- 加密
- update `testmd5` set `pwd` = md5(`pwd`)
- -- 插入时加密
- insert into `testmd5`(`id`,`name`,`pwd`) values('6','小明',md5('123654'))
- -- 查询
- select * from `testmd5` where `name` = '小明' and `pwd` = md5('123654')
复制代码CRUD操作-read
- -- =========================================== 事务 =============================================
- -- mysql 默认开启事务自动提交
- set autocommit = 0 -- 关闭自动提交
- -- 事务开启
- start transaction -- 标记一个事务的开始,从这个之后的 sql 都在同一个事务内
- insert xx
- insert xx
- -- 提交:持久化(成功)
- commit
- -- 回滚:回到原来的样子(失败)
- rollback
- -- 事务结束
- set autocommit = 1 -- 开启自动提交
- -- 了解
- savepoint 保存点名 -- 设置一个事务的保存点
- rollback to savepoint 保存点名 -- 回滚到保存点
- release savepoint 保存点名 -- 撤销保存点
复制代码代码实现
- 提取工具类
- -- 转账
- create database money character set utf8 collate utf8_general_ci;
- use money;
- create table `account`(
- `id` int(3) not null auto_increment,
- `name` VARCHAR(30) not null,
- `money` decimal(9,2) not null,
- primary key(`id`)
- )engine = innodb default charset = utf8
- insert into `account` (`name`,`money`)
- values ('a',2000.00),
- ('b',1000.00)
- -- 模拟转账
- set autocommit = 0; -- 关闭自动提交
- start transaction; -- 开启事务
- update `account` set `money` = `money` - 500 where `name` = 'a'; -- a给b转500
- update `account` set `money` = `money` + 500 where `name` = 'b'; -- b收到a的500
- commit; -- 提交,持久化
- rollback; -- 回滚,提交后没法回滚
- set autocommit = 1; -- 开启自动提交
复制代码 配置文件db.properties
- -- 索引的使用
- -- 1.在创建表的时候给字段增加索引
- -- 2.创建完毕后,增加索引
- -- 显示所有的索引信息
- SHOW INDEX FROM student;
- -- 新增一个索引 (索引名) 列名
- ALTER TABLE `student` ADD UNIQUE KEY `UK_IDENTITY_CARD` (`identity_card`);
- ALTER TABLE `student` ADD KEY `K_STUDENT_NAME`(`student_name`);
- ALTER TABLE `student` ADD FULLTEXT INDEX `FI_PHONE` (`phone`);
- -- explain 分析sql执行的状况
- EXPLAIN SELECT * FROM student; -- 非全文索引
- EXPLAIN SELECT * FROM student WHERE MATCH(`phone`) AGAINST('138'); -- 全文索引
复制代码 - 编写增删改的方法,executeUpdate
- CREATE TABLE `app_user` (
- `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
- `name` VARCHAR(50) DEFAULT'' COMMENT'用户昵称',
- `email` VARCHAR(50) NOT NULL COMMENT'用户邮箱',
- `phone` VARCHAR(20) DEFAULT'' COMMENT'手机号',
- `gender` TINYINT(4) UNSIGNED DEFAULT '0'COMMENT '性别(0:男;1:女)',
- `password` VARCHAR(100) NOT NULL COMMENT '密码',
- `age` TINYINT(4) DEFAULT'0' COMMENT '年龄',
- `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
- `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- PRIMARY KEY (`id`)
- ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT = 'app用户表'
- -- 插入100万数据.
- DELIMITER $$
- -- 写函数之前必须要写,标志
- CREATE FUNCTION mock_data ()
- RETURNS INT
- BEGIN
- DECLARE num INT DEFAULT 1000000;
- DECLARE i INT DEFAULT 0;
- WHILE i<num DO
- INSERT INTO `app_user`(`name`,`email`,`phone`,`gender`,`password`,`age`)
- VALUES(CONCAT('用户',i),'19224305@qq.com',concat('18',floor(rand()*999999999)),
- FLOOR(RAND()*2),uuid(),floor(rand()*100));
- SET i=i+1;
- END WHILE;
- RETURN i;
- END;
- SELECT mock_data() -- 执行此函数 生成一百万条数据
- select * from app_user where `name` = '用户99999'; -- 0.421sec
- explain select * from app_user where `name` = '用户99999'; -- 992742rows
- -- id_表名_字段名
- -- create index 索引名 on 表名(字段名)
- create index id_app_user_name on app_user(`name`);
- select * from app_user where `name` = '用户99999'; -- 0.001sec
- explain select * from app_user where `name` = '用户99999'; -- 1row
复制代码- -- 创建用户
- CREATE USER leez01 IDENTIFIED BY '123456';
- -- 修改密码(修改当前用户密码)
- SET PASSWORD = PASSWORD('123456');
- -- 修改密码(修改指定用户密码)
- SET PASSWORD FOR leez01 = PASSWORD('123456');
- -- 重命名 RENAME 原名子 leez TO 新名字;
- RENAME USER leez01 TO leez;
- -- 用户授权 ALL PRIVILEGES 全部的权限,库,表
- -- ALL PRIVILEGES 除了给别人授权不行,其他都能干
- GRANT ALL PRIVILEGES ON *.* TO leez;
- -- 查询权限
- SHOW GRANTS FOR leez; -- 查看指定用户的权限
- SHOW GRANTS FOR root@localhost; -- 查看root用户的权限
- -- 撤销权限 REVOKE哪些权限,在哪个库,给谁撤销
- REVOKE ALL PRIVILEGES ON *.* FROM leez;
- -- 删除用户
- DROP USER leez;
复制代码- # 一张表 mysqldump -h主机 -u用户名 -p密码 数据库 表名 >物理磁盘位置/文件名
- mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql
- # 多张表 mysqldump -h主机 -u用户名 -p密码 数据库 表名1 表名2 >物理磁盘位置/文件名
- mysqldump -hlocalhost -uroot -p123456 school student result >D:/a.sql
- # 数据库 mysqldump -h主机 -u用户名 -p密码 数据库 >物理磁盘位置/文件名
- mysqldump -hlocalhost -uroot -p123456 school >D:/a.sql
- # 导入
- # 登录的情况下,切换到指定的数据库
- # source 备份文件
- # 也可以这样
- mysql -u用户名 -p密码 库名<备份文件
复制代码 - 查询
- CREATE DATABASE jdbcstudy CHARACTER SET utf8 COLLATE utf8_general_ci;
- USER jdbcstudy;
- CREATE TABLE users(
- `id` INT PRIMARY KEY,
- `name` VARCHAR(40),
- `password` VARCHAR(40),
- `email` VARCHAR(60),
- `birthday` DATE
- );
- INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)
- VALUES(1,'张三','123456','zs@sina.com','1980-12-04'),
- (2,'李四','123456','lisi@sina.com','1981-12-04'),
- (3,'王五','123456','wangwu@sina.com','1982-12-04');
复制代码 10.3 SQL注入
sql存在漏洞,会被攻击导致数据泄露 SQL会被拼接- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- public class JDBCDemo01 {
- public static void main(String[] args) throws ClassNotFoundException, SQLException {
- //1.加载驱动
- Class.forName("com.mysql.jdbc.Driver");
- //2.用户信息和URL
- // useSSL=true可能会报错
- String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";
- String userName = "root";
- String passWord = "";
- //3.连接成功,数据库对象 Connection代表数据库
- Connection connection = DriverManager.getConnection(url, userName, passWord);
- //4.执行SQl的对象 Statement 执行的sql对象
- Statement statement = connection.createStatement();
- //5.执行SQL的对象去执行SQL ,可能存在结果,查看返回的结果
- String sql = "SELECT * FROM users";
- //返回的结果集 结果集中封装了我们全部的查询的结果
- 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("password="+resultSet.getObject("password"));
- System.out.println("email="+resultSet.getObject("email"));
- System.out.println("birthday="+resultSet.getObject("birthday"));
- System.out.println("===============================");
- }
- //6.释放连接
- resultSet.close();
- statement.close();
- connection.close();
- }
- }
复制代码 导致结果:错误的用户名或者密码可以获取到全部的用户信息
10.4 preparement对象详解
PreparedStatement可以防止SQL注入,效率更好
- 新增
- //1.加载驱动
- //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
- //推荐这种写法加载驱动
- Class.forName("com.mysql.jdbc.Driver");
- Connection connection = DriverManager.getConnection(url, userName, passWord);
- // connection代表数据库
- // 数据库设置自动提交
- // 事务提交
- // 事务回滚
- connection.setAutoCommit(true);
- connection.commit();
- connection.rollback();
复制代码 - 删除
- String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";
- // mysql默认端口3306
- // 协议://主机地址:端口号/数据库名?参数1&参数2&参数3
- // oracle默认端口1521
- // jdbc:oracle:thin:@localhost:1521:sid
复制代码 - 更新
- String sql = "SELECT * FROM users";//编写SQL
- statement.executeQuery();//执行查询 返回ResultSet
- statement.executeUpdate();//新增,删除,修改,都用这个,返回受影响的行数
- statement.execute();//执行任何SQL
复制代码 - 查询
- //在不知道列类型的情况下使用
- resultSet.getObject();
- //如果知道列类型,就使用指定的类型
- resultSet.getString();
- resultSet.getInt();
- resultSet.getDouble();
- resultSet.getBigDecimal();
- resultSet.getFloat();
- resultSet.getDate();
- //...
复制代码 - 防止sql注入
- resultSet.beforeFirst();//移动到最前面
- resultSet.afterLast();//移动到最后面
- resultSet.next();//移动到下一个数据
- resultSet.previous();//移动到前一行
- resultSet.absolute(row);//移动到指定行
复制代码 执行结果:查不到任何结果
10.5 事务
要么都成功,要么都失败
ACID原则
- 原子性:要么全部成功,要么全部失败
- 一致性:总数不变
- 隔离性:多个进程互不干扰
- 持久性:一旦提交不可逆,持久化到数据库了
隔离性的问题:
- 脏读:一个事务读取了另外一个没有提交的事务
- 不可重复读:在同一个事务内,重复读取表中数据,表数据发生了改变
- 幻读:在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致
代码实现
- 开启事务con.setAutoCommit(false);
- 一组业务执行完毕,提交事务
- 可以在catch语句中显示的定义回滚语句,但是默认失败就会回滚
正常情况- resultSet.close();
- statement.close();
- connection.close();//消耗资源
复制代码 异常情况- Statement statement = connection.createStatement();
- String sql = "insert into user(...) values(...)";
- int num = statement.executeUpdate(sql);
- if (num > 0) {
- System.out.println("插入成功~");
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |