MySQL学习笔记

2

 

2.2数据库的列类型

数值

  • tinyint 十分小的数值 1个字节

  • smallint 较小的数据 2个字节

  • mediumint 中等大小的数据 3个字节

  • int 标准的整数 4个字节(常用的)

  • bigint 较大的数据 8个字节

  • float 浮点数 4个字节

  • double 浮点数 8个字节(精度问题)

  • decimal 字符串形式的浮点数 金融计算的时候,一般使用

字符串

  • char 字符串固定大小 0-255

  • varchar 可变字符串 0-65535 常用的变量(String)

  • tinytext 微型文本 2^8-1

  • text 文本串 2^16-1 保存大文本

时间日期

java.util.Date

 

  • date YYYY-MM-DD,日期

  • time HH:mm:ss 时间格式

  • datetime YYYY-MM-DD HH:mm:ss 最常用的时间格式

  • timestamp 时间戳, 1970.1.1到现在的毫秒数,也较为常用

  • year 年份表示

null

  • 空值,未知

  • ==注意,不要是用NULL进行运算,使用的结果为NULL

 

2.3 数据库的字段属性(重点)

Unsigned

  • 无符号的整数

  • 声明了该列不能声明为负数

 

zreofill

  • 0填充的

  • 不足的位数,使用0来填充,int(3) 5---005

 

自增

  • 通常理解为自增,自动在上一条记录的基础+1(默认)

  • 通常用来设计唯一的主键 index,必须是整数型

  • 可以自定义主键自增的起始值和步长

非空 NULL not null

  • 假设设置为 not null,如果不给它赋值,就会报错

  • NULL,如果不写值,默认就是null

默认

  • 设置默认的值

  • sex,默认值为男,如果不指定该列的值,则会有默认的值

 

2.4 创建数据库表

CREATE TABLE IF NOT EXISTS `student`(
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT ‘学号‘,
`name` VARCHAR(30) NOT NULL DEFAULT ‘匿名‘ COMMENT‘姓名‘,
`password` VARBINARY(20) NOT NULL DEFAULT ‘123456‘ COMMENT‘密码‘,
`birthday` DATETIME DEFAULT NULL COMMENT ‘出生日期‘,
`address` VARBINARY(100) DEFAULT NULL COMMENT ‘家庭地址‘,
`email` VARBINARY(50) DEFAULT NULL COMMENT ‘邮箱‘,
PRIMARY KEY(`id`)
?
) ENGINE=INNODB DEFAULT CHARSET=utf8

格式

CREATE TABLE [IF NOT EXISTS] `表名`(
  `字段名` 列类型 [属性] [索引] [注释],
  `字段名` 列类型 [属性] [索引] [注释],
  `字段名` 列类型 [属性] [索引] [注释],
  .........
  `字段名` 列类型 [属性] [索引] [注释]
)[表类型][字符集设置][注释]

常用命令

SHOW CREATE DATABASE 库名 --查看创建数据库的语句
SHOW CREATE TABLE 表名 --查看表的定义语句
DESC 表名 --显示表的结构

2.5 数据表的类型

--数据库引擎
/*
INNODB 默认使用
MYISAM 早些年使用
*/
  MYISAM INNODB
事务支持 不支持 支持
数据行锁定 不支持 支持
外键约束 不支持 支持
全文索引 支持 支持
表空间的大小 较小 较大,约为MYSAM的两倍

常规使用操作:

  • MYISAM 节约空间,速度较快

  • INNODB 安全性高,事务的处理,多表多用户操作

 

在物理空间存在的位置

所有的数据库文件都存在 data 目录下

本质还是文件的存储

MySQL引擎在物理文件上区别

  • INNODB 在数据库表中只有一个*.frm文件,以及上级目录下的 ibdata1 文件

  • MYISAM 对应文件

    • *.frm - 表结构的定义文件

    • *.MYD 数据文件(data)

    • *.MYI 索引文件(index)

 

 

设置数据库表的字符集编码

CHARSET=utf8 

不设置的话,会是mysql默认的字符集编码

默认是Latin1,不支持中文

  • 在my.ini中配置默认的编码

character-set-server=utf8

2.6 修改

修改

--修改表名: ALTER TABLE 旧表名 RENAME AS 新表名
ALTER TABLE teacher RENAME AS teacher1
--增加表的字段: ALTER TABLE 表名 ADD 字段名 列属性
ALTER TABLE teacher1 ADD age INT(11)
--修改表的字段 (重命名,修改约束!)
ALTER TABLE表名MODIFY字段名列属性[]
ALTER TABLE teacher1 MODIFY age VARCHAR(11) -- 修改约束
-- ALTER TABLE 表名 CHANGE 旧名字 新名字 列属性[]
ALTER TABLE teacher1 CHANGE age age1 INT(1) -- 字段重名名
?
?
--删除表的字段:   ALTER TABLE表名DROP字段名
ALTER TABLE teacher1 DROP age1
?
--删除表
DROP TABLE IF EXISTS 表名

 

删除

--删除表
DROP TABLE IF EXISTS 表名

 

注意点:

  • ` 所有字段名使用````包裹

  • 注释 -- /**/

  • sql 关键字大小写不敏感,建议小写

  • 所有的符号用英文

 

3 MySQL数据管理

3.1外键 (了解)

方式一、在创建表的时候,增加约束(麻烦, 比较复杂)

CREATE TABLE‘grade (
	`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT ‘年级id‘,
	`gradename` VARCHAR(50) NOT NULL COMMENT ‘年级名称‘,
	PRIMARY KEY (`gradeid` )
) ENGINE=INNODB DEFAULT CHARSET=utf8

--学生表的gradeid字段要去引用年级表的gradeid
--定义外键key
--给这个外键添加约束(执行引用) references引用


CREATE TABLE IF NOT EXISTS `student`(
	`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 ‘出生日期‘,
	`gradeid` INT(10) NOT NULL COMMENT ‘ 学生的年级‘,
	`address` VARCHAR (100) DEFAULT NULL COMMENT ‘家庭住址‘ ,
	`email` VARCHAR(50) DEFAULT NULL COMMENT ‘邮箱‘,
	PRIMARY KEY(`id`),
	KEY‘FK_ gradeid ( gradeid ),
	CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

删除有外键关系的表的时候,必须要先删除引用别人的表 (从表) 再删除被引用的表(主表)

方式二:创建成功表后,添加外键约束

CREATE TABLE `grade` (
	`gradeid` INT(10) NOT NULL AUTO_ INCREMENT COMMENT ‘年级id‘,
	`gradename` VARCHAR(50) NOT NULL COMMENT ‘年级名称‘,
	PRIMARY KEY (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
--学生表的gradeid 字段要去引用年级表的gradeid
--定义外键key 
--给这个外键添加约束(执行引用) references 引用
CREATE TABLE IF NOT EXISTS`student`(
	`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 ‘出生日期‘,
	`gradeid` INT(10) NOT NULL COMMENT ‘学生的年级‘,
	`address` VARCHAR (100) DEFAULT NULL COMMENT ‘家庭住址‘,
	`emai1` VARCHAR(50) DEFAULT NULL COMMENT ‘邮箱‘,
	PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 创建表的时候没有外键关系
ALTER TABLE `student`
ADD CONSTRAINT `FK_ gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade` (`gradeid`);
-- ALTER TABLE 表 ADD CONSTRAINT 约束名 FOREIGN KEY(作为外键的列) REFERENCES 那个表(哪个字段)

 

以上操作都是物理外键,数据库级别的外键,不建议使用(避免数据库过多造成混乱)

==最佳实践==

  • 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段) 我们想使用多张表的数据,想使用外键(程序去实现)

3.2 DML语言(记住)

  • insert

  • update

  • delete

3.3 添加

insert

插入语句(添加)
insert into 表名([字段名1,字段2,字段3])values(‘值1‘),(‘值2‘),(‘值3‘),...
INSERT INTO `grade` (`gradename`) VALUES(‘ 大四‘)
--由于主键自增我们可以省略(如果不写表的字段,他就会一- -匹配)
INSERT INTO `grade` VALUES(‘大三‘)
--一般写插入语句,我们一定要数据和字段一一对应!
--插入多个字段
INSERT INTO `grade` (`gradename`)
VALUES(‘大二‘),(‘大一‘)
INSERT INTO `student` (`name`) VALUES (‘张三‘)
INSERT INTO `student` ( `name`,`pwd`,`sex`) VALUES (‘张三‘ ,‘aaaaaa‘,‘男‘)
INSERT INTO `student` (`name`,`pwd`,`sex` )
VALUES (‘李四‘,‘aaaaa‘,‘男‘),(‘王五‘,‘aaaaa‘,‘男‘)

语法:

insert into 表名([字段名1,字段2,字段3])values(‘值1‘),(‘值2‘),(‘值3‘),

注意:

  1. 字段和字段之间使用英文逗号隔开

  2. 字段是可以省略的,但是后面的值必须要要一- 对应,不能少

  3. 可以同时插入多条数据,VALUES 后面的值,需要使用,隔开即可 `VALUES(),()``

3.4 修改

update 修改谁 (条件) set原来的值=新值

 

--修改学员名字,带了简介
UPDATE `student` SET `name`=‘冬冬‘ WHERE id = 1;

--不指定条件的情况下,会改动所有表!
UPDATE`student` SET `name`=‘冬冬1号‘

--修改多个属性,逗号隔开
UPDATE `student` SET `name` =‘冬冬‘,`email` =‘77511593@qq. com‘ WHERE id = 1;
--语法:
-- UPDATE 表名set colnum_name = value,[colnum_name = value,....] where [条件]

条件:where子句 运算符id等于某个值,大于某个值,在某个区间内修改.

操作符 含义
= 等于
<>或!= 不等于
>  
<  
>=  
<=  
BETWEEN...AND... 在某个范围内
AND  
OR  
  • 通多多个条件定位数据

语法:UPDATE 表名 set colnum_name = vlaue,[colnum_name = value,....] where[条件]

注意:

  • colnum_name是数据库的列,尽量带上"

  • 条件,筛选的条件,如果没有指定,则会修改所有的列

  • value,是一个具体的值,也可以是一个变量

  • 多个设置的属性之间,使用英文逗号隔开

3.5 删除

delete 命令

语法:dalete from 表名 [where 条件]

--删除数据(避免这样写,会全部删除)
DEL ETE FROM `student`
--删除指定数据
DELETE FROM `student` WHERE id = 1;

TRUNCATE 命令

完全清空一个数据库表,表的结构和索引约束不会变

TRUNCATE 表名

delete的TRUNCATE区别

  • 不同:

    • TRUNCATE重新设置自增列计数器会归零

    • TRUNCATE不会影响事务

--测试delete和TRUNCATE 区别
CREATE TABLE `test` (
	id INT(4) NOT NULL AUTO_INCREMENT,
	`co11` VARCHAR(20) NOT NULL,
	PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `test` ( `coll`) VALUES(‘1‘),(‘2‘),(‘3‘)

DELETE FROM `test` -- 不会影响自增

TRUNCATE TABLE `test` --自增会归零

了解:DELETE删除的问题。删除之后重启数据库,现象

  • InnoDB 自增列会重1开始(存在内存当中的, 断电即失)

  • MyISAM 继续从上一个自增量开始(存在文件中的, 不会丢失)

 

4 DQL查询数据(最重点)

 

4.1 DQL

(Data Query Language:数据查询语言)

  • 所有的查询操作都用它Select

  • 简单的查询,复杂的查询它都能做~

  • 数据库中最核心的语言,最重要的语句

  • 使用频率最高的语句

MySQL学习笔记

4.2 指定查询字段

--查询全部的学生  SELECT字段   FROM表
	SELECT * FROM student

--查询指定字段
SELECT `StudentNo`,`StudentName` FROM student

--别名,给结果起一个名字 AS,可以给字段起别名, 也可以给表起别名
SELECT `StudentNo` AS 学号,`StudentName` AS 学生姓名 FROM student AS 新名字

--函数Concat (a,b)
SELECT CONCAT(‘姓名:‘,StudentName) AS 新名字 FROM student

语法:select 字段,.....from 表

 

 

去重 distinct

作用:去除SELECT 查询出来的结果中重复的数据,重复的只显示一条

查询一下有哪些同学参加了考试,成绩
SELECT * FROM result -- 查询全部的考试成绩
SELECT `StudentNo` FROM result --查询有哪些同学参加了考试
SELECT DISTINCT `StudentNo` FROM result --发现重复数据,去重

 

数据库的列 (表达式)

SELECT VERSION() -- 查询系统版本(函数)
SELECT 100*3-1 AS计算结果 --用来计算(表达式)
SELECT @@auto_increment_increment --查询自增的步长(变量)
学员考试成绩+ 1分查看
SELECT `StudentNo`,`StudentResult`+1 AS ‘提分后‘ FROM result

数据库中的表达式: 文本值,列,Null,函数,计算表达式,系统变量....

select 表达式 from 表达式

 

4.3 where 条件子句

作用: 检索数据中符合条件的值

 

逻辑运算符

运算符 语法 描述
and && a and b a&&b 逻辑与,两个都为真,结果为真
or || a or b a||b 逻辑或,其中一个为真,则结果为真
Not ! not a !a 逻辑非,真为假,假为真

尽量使用英文字母

 

--查询考试成绩在95~100 分之间
SELECT `studentNo`,`StudentResult` FROM result
WHERE StudentResult>=95 AND StudentResult<=100


模糊查询(区间)
SELECT `studentNo`,`StudentResult` FROM result
WHERE `StudentResult` BETWEEN 95 AND 100

--除了1000号学生之外的同学的成绩
SELECT `studentNo`,`StudentResult` FROM result
WHERE NOT `StudentResult` =1000     (WHERE `StudentResult` !=1000 )

 

模糊查询: 比较运算符

 

运算符 语法 描述
IS NULL a is null 如果操作符为NULL,结果为真
IS NOT NULL a is not null 如果操作符不为NULL,结果真
BETWEEN a between b and c 若a在b和c之间,则结果为真
Like a like b SQL匹配,如果a匹配b,则结果为真
In a in (a1,a2,a3...) 假设a在a1,或者a2...其中的某一个值中,结果为真
--===================模糊查询======================
--查询姓刘的同学
-- like结合 号(代表0到任意个字符)_ (一 个字符)
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentName LIKE ‘刘%‘

--查询姓刘的同学,名字后面只有一个字的
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentName LIKE ‘刘_‘

--查询姓刘的同学,名字后面只有两个字的
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentName LIKE ‘刘__‘

--查询名字中间有嘉字的同学  %嘉%
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentName LIKE ‘%嘉%‘

-- ====== in (具体的一个或者多个值) ===
--查询1001, 1002, 1003号学员
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentNo IN (1001,1002,1003);
--查询在北京的学生
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `Address` IN (‘安徽‘,‘河南洛阳‘) ;

-- ==== nullnot null====
查询地址为空的学生null
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE addrress=‘‘ OR address IS NULL
--查询有出生日期的同学 不为空
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `BornDate` IS NOT NULL
--查询没有有出生日期的同学I为空
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `BornDate` IS NULL

 

 

4.4 联表查询

JOIN 对比

MySQL学习笔记

MySQL学习笔记

 

MySQL学习笔记

 

--INNER JOIN
/* 思路
1.分析需求,分析查询的字段来自哪些表, (连接查询)
2.确定使用哪种连接查询?7种
确定交叉点(这两个表中哪个数据是相同的).
判断的条件:学生表的中 studentNo =成绩表studentNo
*/
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student AS s
INNER JOIN result AS r
WHERE s.studentNO = r.studentNO

 

 

 

MySQL学习笔记

-- Right Join
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student AS s
RIGHT JOIN result AS r
ON s.studentNO = r.studentNO

 

 

 

MySQL学习笔记

-- Left Join
SELECT s.studentNO,studentName,SubjectNo,StudentResult
FROM student AS s
LEFT JOIN result AS r
ON s.studentNO = r.studentNO

 

操作 描述
Inner Join 如果表中至少有一个匹配,就返回行
Right Join 会从左表中返回所有的值,即使右表中没有匹配
Left Join 会从右表中返回所有的值,即使左表中没有匹配
  • join (连接的表) on (判断的条件) 连接查询

  • where 等值查询

 

--思考题(查询了参加考试的同学信息:学号, 学生姓名,科目名,分数)
/*思路
分析需求,分析查询的字段来自哪些表,:
student、result、 subject ( 连接查询)
2.确定使用哪种连接查询?7种
确定交叉点(这两个表中哪个数据是相同的)
判断的条件:学生表的中studentNo =成绩表studentNo
*/
SELECT s.studentNo,studentName,SubjectName,`StudentResult`
FROM student s
RIGHT JOIN result r
ON r.studentNo = s.studentNo
INNER JOIN、 subject sub
ON r.SubjectNo = sub.SubjectNo

--我要查询哪些数据:
--select
--从那几个表中查FROM 表XXX Join连接的表
--on 交叉条件
--假设存在--种多张表查询,慢慢来,先查询两张表然后再慢慢增加

 

 

自连接(了解)

自己的表和自己的表连接,核心:一张表拆为两张一样的表即可

CREATE TABLE `school`.`category`( `categoryid` INT(3) NOT NULL COMMENT ‘id‘, `pid` INT(3) NOT NULL COMMENT ‘父id 没有父则为1‘, `categoryname` VARCHAR(10) NOT NULL COMMENT ‘种类名字‘, PRIMARY KEY (`categoryid`) ) ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci;

INSERT INTO `school`.`category` (`categoryid`, `pid`, `categoryname`) VALUES (‘2‘, ‘1‘, ‘信息技术‘);
insert into `school`.`CATEGOrY` (`categoryid`, `pid`, `categoryname`) values (‘3‘, ‘1‘, ‘软件开发‘);
insert into `school`.`category` (`categoryid`, `PId`, `categoryname`) values (‘5‘, ‘1‘, ‘美术设计‘);
insert iNTO `School`.`category` (`categoryid`, `pid`, `categoryname`) VAlUES (‘4‘, ‘3‘, ‘数据库‘);
insert into `school`.`category` (`CATEgoryid`, `pid`, `categoryname`) values (‘8‘, ‘2‘, ‘办公信息‘);
insert into `school`.`category` (`categoryid`, `pid`, `CAtegoryname`) values (‘6‘, ‘3‘, ‘web开发‘);
inserT INTO `SCHool`.`category` (`categoryid`, `pid`, `categoryname`) valueS (‘7‘, ‘5‘, ‘ps技术‘);

父类

categoryid categoryname
2 信息技术
3 软件开发
5 美术设计

子类

pid categoryid categoryname
3 4 数据库
2 8 办公信息
3 6 web开发
5 7 ps技术

操作:查询父类对应的子类关系

父类 子类
信息技术 办公信息
软件开发 数据库
软件开发 web开发
美术设计 ps技术

 

SELECT a.`categoryname` AS ‘父栏目‘,b.`categoryname`AS ‘子栏目‘
FROM `category` AS a,`category` AS b
WHERE a.`categoryid` = b.`pid`

 

4.5 分页和排序

排序

--===分页limit 和排序order by ===============
--排序:升序ASC,降序DESC
--ORDER BY通过那个字段排序,怎么排
--查询的结果根据成绩降序排序
SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN‘ result r
ON s.`StudentNo` = r.`StudentNo`
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`Subj ectNo`
WHERE subjectName = ‘数据库结构-1‘
ORDER BY StudentResult ASC

 

分页

-- 100万
--为什么要分页?
--缓解数据库压力,给人的体验更好,瀑布流
--分页,每页只显示五条数据
--语法: limit 起始值,页面的大小
--网页应用:当前,总的页数,页面的大小
-- LIMIT 0, 5  1~5
-- LIMIT 1,5  2~6
-- Limit 5,5
SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM `student` s
INNER JOIN `result` r
ON s.`StudentNo`= r.`StudentNo`
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
WHERE `subjectName` = ‘数据库结构-1‘
ORDER BY `StudentResult` ASC
LIMIT 5,5
--第一页limit 0,5 (1-1) *5
--第二页1imit 5,5 (2-1) *5
--第三页1imit 10,5 (3-1) *5
--第N页 limit 0,5		(n-1) * pagesize, pagesize
-- [pagesize: 页面大小]
-- [(n-1)* pagesize :起始值]
-- [n:当前页]
-- [数据总数/页面大小=总页数]

 

语法: limit(查询起始下标)

 

4.6子查询(由里及外)

--分数不小于80分的学生的学号和姓名
SELECT DISTINCT s.`StudentNo`,`StudentName`
FROM student s 
INNER JOIN result r
ON r.studentNo = s.studentNo
WHERE `StudentResult`>=80

--在这个基础上增加一个科目, 高等数学-2
--查询高等数学-2的编号
SELECT DISTINCT s.`StudentNo`,`StudentName`
FROM student S 
INNER JOIN result r
ON r.StudentNo = s.StudentNo
WHERE `StudentResul`>=80 AND `SubjectNo` = (
SELECT SubjectNo FROM `subject`
WHERE `subjectName` = ‘高等数学-2‘
)
--在改造(由里及外)
SELECT StudentNo,studentName FROM student WHERE StudentNo IN (
SELECT StudentNo FROM result WHERE StudentResult>80 AND SubjectNo = (SELECT subjectNo FROM `subject` WHERE `SubjectName` = ‘高等数学-2‘)
)

 

4.7分组和过滤

--查询不同课程的平均分,最高分,最低分,平均分大于80 !
--核心: (根据不同的课程分组)
SELECT SubjectName,AVG(StudentResult) AS平均分, MAX(StudentResu1t) AS最高分, MIN(StudentResult) AS 最低分
FROM result r
INNER JOIN `subject` sub
ON r.`subjectNo` = sub.`SubjectNo`
GROUP BY r.SubjectNo --通过什么字段来分组
HAVING平均分>80

 

MySQL函数

https://www.runoob.com/mysql/mysql-functions.html

5.1 常用函数

MySQL 数字函数 (一部分)

函数名 描述 实例
ABS(x) 返回 x 的绝对值 返回 -1 的绝对值:SELECT ABS(-1) -- 返回1
ACOS(x) 求 x 的反余弦值(参数是弧度) SELECT ACOS(0.25);
ASIN(x) 求反正弦值(参数是弧度) SELECT ASIN(0.25);
ATAN(x) 求反正切值(参数是弧度) SELECT ATAN(2.5);
ATAN2(n, m) 求反正切值(参数是弧度) SELECT ATAN2(-0.8, 2);
AVG(expression) 返回一个表达式的平均值,expression 是一个字段 返回 Products 表中Price 字段的平均值:SELECT AVG(Price) AS AveragePrice FROM Products;
CEIL(x) 返回大于或等于 x 的最小整数 SELECT CEIL(1.5) -- 返回2
CEILING(x) 返回大于或等于 x 的最小整数 SELECT CEIL(1.5) -- 返回2

MySQL 字符串函数

函数 描述 实例
ASCII(s) 返回字符串 s 的第一个字符的 ASCII 码。 返回 CustomerName 字段第一个字母的 ASCII 码:SELECT ASCII(CustomerName) AS NumCodeOfFirstChar FROM Customers;
CHAR_LENGTH(s) 返回字符串 s 的字符数 返回字符串 RUNOOB 的字符数SELECT CHAR_LENGTH("RUNOOB") AS LengthOfString;
CHARACTER_LENGTH(s) 返回字符串 s 的字符数 返回字符串 RUNOOB 的字符数SELECT CHARACTER_LENGTH("RUNOOB") AS LengthOfString;
CONCAT(s1,s2...sn) 字符串 s1,s2 等多个字符串合并为一个字符串 合并多个字符串SELECT CONCAT("SQL ", "Runoob ", "Gooogle ", "Facebook") AS ConcatenatedString;
CONCAT_WS(x, s1,s2...sn) 同 CONCAT(s1,s2,...) 函数,但是每个字符串之间要加上 x,x 可以是分隔符 合并多个字符串,并添加分隔符:SELECT CONCAT_WS("-", "SQL", "Tutorial", "is", "fun!")AS ConcatenatedString;
FIELD(s,s1,s2...) 返回第一个字符串 s 在字符串列表(s1,s2...)中的位置 返回字符串 c 在列表值中的位置:SELECT FIELD("c", "a", "b", "c", "d", "e");

 

MySQL 日期函数

 

数名 描述 实例
ADDDATE(d,n) 计算起始日期 d 加上 n 天的日期 SELECT ADDDATE("2017-06-15", INTERVAL 10 DAY); ->2017-06-25
ADDTIME(t,n) 时间 t 加上 n 秒的时间 SELECT ADDTIME(‘2011-11-11 11:11:11‘, 5) ->2011-11-11 11:11:16 (秒)
CURDATE() 返回当前日期 SELECT CURDATE(); -> 2018-09-19
CURRENT_DATE() 返回当前日期 SELECT CURRENT_DATE(); -> 2018-09-19
CURRENT_TIME 返回当前时间 SELECT CURRENT_TIME(); -> 19:59:02
CURRENT_TIMESTAMP() 返回当前日期和时间 SELECT CURRENT_TIMESTAMP() -> 2018-09-19 20:57:43
CURTIME() 返回当前时间 SELECT CURTIME(); -> 19:59:02

 

5.2聚合函数(常用)

AVG 求平均值
COUNT 统计行的数量
MAX 求最大值
MIN 求最小值
SUM 求累加和

 

COUNT() 函数返回匹配指定条件的行数。


SQL COUNT(column_name) 语法

COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):

SELECT COUNT(column_name) FROM table_name;

SQL COUNT(*) 语法

COUNT(*) 函数返回表中的记录数:

SELECT COUNT(*) FROM table_name;

SQL COUNT(DISTINCT column_name) 语法

COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:

SELECT COUNT(DISTINCT column_name) FROM table_name;

注释:COUNT(DISTINCT) 适用于 ORACLE 和 Microsoft SQL Server,但是无法用于 Microsoft Access。

--===========聚合函数===============
--都能够统计表中的数据( 想查询一个表中有多少个记录,就使用这个count () )
SELECT COUNT (`BornDate`) FROM student; --Count(字段),会忽略所有的null 值
SELECT COUNT (*) FROM student; -- Count (*),不会忽略null值, 本质计算行数
SELECT COUNT (1) FROM result; -- Count (1),不会忽略忽略所有的null 值本质计算行数
SELECT SUM(`StudentResult`) AS总和FROM result
SELECT AVG(`StudentResulti`) AS平均分FROM result
SELECT MAX(`StudentResult`) AS最高分FROM result
SELECT MIN(`StudentResult`) AS最低分FROM result

 

5.3 数据库级别的MD5加密(扩 展)

 

--=========测试MD5加密=======
CREATE TABLE `testmd5`(
id INT(4) NOT NULL,
name VARCHAR(20) NOT NULL,
pwd VARCHAR(50) NOT NULL,
PRIMARY KEY(`idi`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
--明文密码
INSERT INTO testmd5 VALUES(1,‘ zhangsan‘,‘123456‘),(2,‘lisi‘,‘123456‘),(3,‘wangwu‘,‘123456‘)
--加密
UPDATE testmd5 SET pwd=MD5 (pwd) WHERE id = 1

UPDATE testmd5 SET pwd=MD5 (pwd) -- 加密全部的密码

--插入的时候加密

INSERT INTO testmd5 VALUES(4,‘xiaoming‘,MD5(‘123456‘))

--如何校验:将用户传递进来的密码,进行md5加密,然后比对加密后的值

SELECT * FROM testmd5 WHERE `name` =‘xiaoming‘ AND pwd=MD5(‘123456‘)

 

6 事务

 

6.1 什么是事务

要么都成功,要么都失败

参考链接https://blog.csdn.net/dengjili/article/details/82468576

 

事务原则: ACID原则 原子性,一致性,隔离性,持久性 (脏读,幻读....

原子性(Atomicity) 要么都成功,要么都失败 一致性 (Consistency) 事务前后的数据完整性要保证一致,1000 持久性(Durability) -- 事务提交 事务一旦提交则不可逆,被持久化到数据库中! 隔离性(Isolation) 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

 

隔离所导致的一些问题

脏读: 指一个事务读取了另外-个事务未提交的数据。 不可重复读: 在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一 -定是错误, 只是某些场合不对) 虚读(幻读) 是指在- -个事务内读取到了别的事务插入的数据,导致前后读取不- -致。

 

--====================事务==========================
-- mysq1 是默认开启事务自动提交的
SET autocommit = 0 /*关闭*/
SET autocommit = 1 /*开启(默认的) */
--手动处理事务
SET autocommit = 0 --关闭自动提交
--事务开启
START TRANSACTION -- 标记一个事务的开始,从这个之后的sq1 都在同一个事务内
INSERT xx
INSERT XX
--提交:持久化(成功! )
COMMIT
--回滚: 回到的原来的样子(失败! )
ROLLBACK 
--事务结束
SET autocommit = 1 --开启自动提交
--了解
SAVEPOINT 保存点名--设置一个事务的保存点
ROLLBACK To SAVEPOINT 保存点名--回滚到保存点
RELEASE SAVEPOINT 保存点名--撤销保存点

 

 

--转账
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_ general_ ci
USE shop
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‘,10000.00)

--模拟转账:事务
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION --开启一个事务(一组事务)

UPDATE account SET money=money-500 WHERE `name` = ‘A‘ -- A减500
UPDATE account SET money=money+500 WHERE `name` = ‘B‘ -- A加500
COMMIT; --提交事务,就被持久化了!
ROLLBACK; -- 回滚

SET autocommit = 1; --恢复默认值

 

 

7 索引

MySQL官方对索引的定义为:索引(Index) 是帮助MySQL高效获取数据的数据结构。 提取句子主干,就可以得到索引的本质:索弓|是数据结构。

 

7.1 索引的分类

  • 主键索引(PRIMARY KEY )

    • 唯一的标识,主键不可重复,只能有一-个列作为主键

  • 唯一索引(UNIQUE KEY)

    • 避免重复的列出现,唯一 索引可以重复,多个列都可以标识位唯一索引

  • 常规索引(KEY/INDEX)

    • 默认的,index。 key关键字来设置

  • 全文索引(FullText)

    • 在特定的数据库|擎下才有,MylSAM

    • 快速定位数据

 

基础语法

--索引的使用
--1、在创建表的时候给字段增加索引
-- 2、创建完毕后,增加索引
--显示所有的索引信息
SHOW INDEX EROM student

--增加一个全文索引 (索引名) 列名
ALTER TABLE school.student ADD FULLTEXT INDEX studentName`(`studentName`) ;
--id_表名_字段名 
--CREATE INDEX 索引名 on 表(字段)
CREATE INDEX id app user name ON app user(`name`) ;

-- EXPLAIN 分析sq1执行的状况
EXPLAIN SELECT * FROM student; -- 非全文索引
EXPLAIN SELECT * FROM student WHERE MATCH(studentName) AGAINST(‘ 刘‘);

索引在小数据量的时候,用处不大,但是在大数据的时候,区别十分明显~

7.3 索引原则

  • 索引不是越多越好

  • 不要对经常变动的数据加索引

  • 小数据量的表不需要加索引

  • 索引一般加在常用来查询的字段上

 

索引的数据结构

https://www.cnblogs.com/tgycoder/p/5410057.html

 

Hash类型的索引 Btree :InnoDB的默认数据结构

 

8 权限管理和备份

8.1 用户管理

SQLyog 可视化管理

MySQL学习笔记

SQL 命令操作

用户表: mysql.user 本质:读这张表进行增删改查

--创建用户CREATE USER用户名IDENTIFIED BY ‘密码‘
CREATE USER dongdong IDENTIFIED BY ‘123456‘

--修改密码(修改当前用户密码)
SET PASSWORD = PASSWORD(‘123456‘)

--修改密码( 修改指定用户密码)
SET PASSWORD FOR dongdong = PASSWORD(‘123456‘ )

--重命名RENAME USER原来名字TO新的名字
RENAME USER dongdong To dongdong2

--用户授权ALL PRIVILEGES 全部的权限,库.表
-- ALL PRIVILEGES 除了给别人授权,其他都能够干
GRANT ALL PRIVILEGES ON *.* TO dongdong2

--查询权限
SHOW GRANTS FOR dongdong2 -- 查看指定用户的权限
SHOW GRANTS FOR root@localhost
-- ROOT用户权限: GRANT ALL PRIVILEGES ON *.* TO ‘ root‘@ ‘localhost‘ WITH GRANT OPTION
--撤销权限REVOKE哪些权限,在哪个 库撒销,给谁撤销
REVOKE ALL PRIVILEGES ON *.* FROM dongdong2
--删除用户
DROP USER dongdong

 

8.2 MySQL 备份

 

为什么要备份:

  • 保证重要的数据不丢失

  • 数据转移

MySQL数据库备份的方式

  • 直接拷贝物理文件

  • 在Sqlyog 这种可视化工具中手动导出

    • 在想要导出的表或者库中,右键,选择备份或导出

  • 使用命令行导出mysqldump

# mysq1dump -h主机-u 用户名 -p 密码 数据库表名 > 物理磁盘位置/文件名
mysq1dump -hTocalhost -uroot -p123456 schoo1 student >D:/a.sq1
# mysq1dump -h主机-u 用户名 -p 密码 数据库 表1 表2 表3 > 物理磁盘位置/文件名
mysqldump -h1ocalhost -uroot -p123456 schoo1 student >D:/b.sq1
# mysq1dump -h主机-u 用户名 -p 密码数据库 > 物理磁盘位置/文件名
mysq1dump -hTocalhost -uroot -p123456 schoo1 >D:/c.sq1

#导入
#登录的情况下,切换到指定的数据库
# source
备份文件
source d:/a.sq1

mysq1 -u 用户名 -p 密码 库名 < 备份文件

 

9 规范数据库设计

9.1 为什么需要设计

当数据库比较复杂的时候,我们就需要设计了 糟糕的数据库设计: 数据冗余,浪费空间

  • 数据库插入和删除都会麻烦、异常[屏蔽使用物理外键]

  • 程序的性能差

良好的数据库设计:

  • 节省内存空间

  • 保证数据库的完整性

  • 方便我们开发系统

软件开发中,关于数据库的设计

  • 分析需求:分析业务和需要处理的数据库的需求

  • 概要设计:设计关系图E-R图

设计数据库的步骤:(个人博客)

  • 收集信息,分析需求

    • 用户表(用户登录注销,用户的个人信息,写博客,创建分类)

    • 分类表(文章分类,谁创建的)

    • 文章表(文章的信息)

    • 友链表(友链信息)

    • 自定义表(系统信息,某个关键的字,或者一 些主字段) key : value

  • 标识实体 (把需求落地到每个字段)

  • 标识实体之间的关系

    • 写博客: user -> blog

    • 创建分类: user -> category

    • 关注: user ->user

    • 友链: links

    • 评论: user-user-blog

9.2 三大范式

 

三大范式

第一范式(1NF) 原子性:保证每-列不可再分 第二范式(2NF) 前提:满足第一范式 每张表只描述- -件事情 第三范式(3NF) 前提:满足第一范式和第二范式 第三范式需要确保数据表中的每一列数据都和主键直 接相关,而不能间接相关。 (规范数据库的设计)

 

规范性和性能的问题

关联查询的表不得超过三张表

  • 考虑商业化的需求和目标,(成本, 用户体验! )数据库的性能更加重

  • 在规范性能的问题的时候,需要适当的考虑一下 规范性!

  • 故意给某些表增加一-些冗余的字段。(从多 表查询中变为单表查询)、

  • 故意增加一-些计算列(从大数据 量降低为小数据量的查询:索引)

 

JDBC(重点)

 

10.1 数据库驱动

 

我们的程序会通过数据库驱动,和数据库打交道

 

10.2 JDBC

 

导入驱动包mysql-connector-java-5.1.47.jar

 

10.3 第一个JDBC程序

 

创建测试数据库

 

CREATE DATABASE jdbcstudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE 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,‘zhansan‘,‘123456‘,‘zs@sina. com‘,‘1980-12-04‘),
(2,‘lisi‘,‘123456‘,‘1isi@sina.com‘,‘1981-12-04‘),
(3,‘wangwu‘,‘123456‘,‘wangwu@sina.com‘,‘1979-12-04‘);

 

  1. 创建一个普通项目

  2. 导入数据库驱动

 

 

编写测试代码

package com.zeng.lesson01;

import java.sql.*;

//我的一个JDBC程序
public class JdbcFirstDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver"); //固定写法:加载驱动

        //2.用户信息和url
        //useUnicode=true&characterEncoding=utf8&useSSL=true
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String username = "root";
        String password = "123456";

        //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("pwd=" + resultSet.getObject("PASSWORD"));
            System.out.println("email=" + resultSet.getObject("email"));
            System.out.println("birth=" + resultSet.getObject("birthday"));
            System.out.println("====================");
        }
        //6、释放连接
        resultSet.close();
        statement.close();
        connection.close();

    }
}

1、加载驱动 2、连接数据库DriverManager 3、获得执行sql的对象Statement 4、获得返回的结果集 5、释放连接

DriverManager

// Drivermanager . regi sterDriver(new com. mysq1. jdbc. Driver());
Class.forName ("com.mysq1.jdbc.Driver"); //固定写法,加载驱动
Connection connection = DriverManager.getConnection(ur1, username, password);
// connection代表数据库
//数据库设置自动提交
//事务提交
//事务滚回
connection. ro11back();
connecti on. commit();
connecti on. setAutoCommit() ;

 

url

String ur1 = "jdbc:mysq1://1ocaThost:3306/jdbcstudy?
useUnicode-true&characterEncoding=utf8&usessL=true";
// mysq1 -- 3306
// 协议://主机地址:端口 号/数据库名?参数1&参数2&参数3
// oralce -- 1521
//jdbc:oracle:thin:@localhost:1521:sid 

 

Statement执行SQL的对象 PrepareStatement 执行SQL的对象

statement.executequery(); //查 询操作返回ResultSet
statement.execute(); //执行任何SQL
statement.executeUpdate(); // 更新、插入、删除。都是用这个,返回一个受影响的行数

 

ResultSet查询的结果集:封装了所有的查询结果

获得指定的数据类型

resultset. getobject(); //在不知道列类型的情况下使用
//如果知道列的类型就使用指定的类型
resultSet.getstring();
resultSet.getInt();
resultset.getFloat();
resultSet.getDate() ;
resultset.getobject();

 

resultSet.beforeFirst(); // 移动到最前面
resultset.afterLast();//移动到最后面
resultset.next(); //移动到下一 -个数据
resultSet.previous(); //移动到前一行
resultset.absolute(row); //移动到指定行

 

释放资源

//6、释放连接
resultSet.close() ;
statement.close() ;
connection.close(); // 耗资源,用完关掉!

 

10.4 statement对象

Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。

Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sq|语句, executeUpdate执行完后, 将会返回-个整数(即增删改语句导致了数据库几行数据发生了变化)。

Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方 法返回代表查询结果的ResultSet对象。

 

CRUD操作- create

使用executeUpdate(String sql)方法完成数据添加操作,示例操作:

 

Statement st = conn.createstatement();
String sql = "insert into user(...) value(.....)";
int num = st. executeUpdate(sql);
if (num>0){
System. out. print1n("插入成功!");
}

 

CRUD操作-delete

使用executeUpdate(String sq|)方法完成数据删除操作,示例操作:

Statement st = conn.createstatement();
string sq1 = "delete from user where id=1";
int num = st.executeUpdate(sql);
if (num>0){
System. out. print1n("删除成功!");
}

 

CRUD操作-update

使用executeUpdate(String sq|)方法完成数据删除操作,示例操作:

Statement st = conn.createstatement();
string sq1 = "update user set name‘‘ where name=‘‘";
int num = st.executeUpdate(sql);
if (num>0){
	System. out. print1n("修改成功!");
}

 

CRUD操作-read

使用executeQuery(String sq|)方法完成数据查询操作,示例操作:

Statement st = conn.createstatement();
string sq1 = "select * from user where id=1";
ResultSet rs = st.executeUpdate(sq1);
whi1e(rs.next()){
		//根据 获取列的数据类型,分别调用rs的相应方法映射到java对象中
}

 

代码实现

  1. 提取工具类

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    private static String driver =null;
    private static String url =null;
    private static String username =null;
    private static String password =null;
    static {

        try {
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(in);

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //驱动只用加载一次
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    //释放连接资源
   public static void release(Connection conn, Statement st, ResultSet rs){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }if (conn!=null){
           try {
               conn.close();
           } catch (SQLException e) {
               e.printStackTrace();
           }

       }
   }
}
  1. 编写增删改 executeUpdate

package com.zeng.lesson02;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TsetInsert {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//获取数据库连接
            st = conn.createStatement();    //获得SQL的执行对象
            String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`)" +
                    "VALUE(6,‘dongdong‘,‘123456‘,‘77511593@qq.com‘,‘2020-04-07‘)";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}
package com.zeng.lesson02;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//获取数据库连接
            st = conn.createStatement();    //获得SQL的执行对象
            String sql = "DELETE FROM users WHERE id = 4";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("删除成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}
package com.zeng.lesson02;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//获取数据库连接
            st = conn.createStatement();    //获得SQL的执行对象
            String sql = "UPDATE users SET `NAME`=‘dongdong2‘,`email`=‘123@qq.com‘ WHERE id=5";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("更改成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}
  1. 查询 executeQuery

 

package com.zeng.lesson02;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//获取数据库连接
            st = conn.createStatement();    //获得SQL的执行对象
            String sql = "select * from users where id = 1";
            rs = st.executeQuery(sql);//查询完毕会返回一个结果集
            while (rs.next()){
                System.out.println(rs.getString("NAME"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

 

SQL注入的问题

sql存在漏洞,会被攻击导致数据泄露,SQL会被拼接or

package com.zeng.lesson02;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Sql注入 {
    public static void main(String[] args) {

        login(" ‘or‘1=1"," ‘or‘1=1");
    }
    public static void login(String username,String password){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//获取数据库连接
            st = conn.createStatement();    //获得SQL的执行对象

            //select * from users where `NAME` = ‘‘or‘1=1‘and `PASSWORD` = ‘‘or‘1=1‘;

            String sql = "select * from users where `NAME` = ‘"+username+"‘and `PASSWORD` = ‘"+password+"‘";
            rs = st.executeQuery(sql);//查询完毕会返回一个结果集
            while (rs.next()){
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("PASSWORD"));
                System.out.println("================");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

10.5 PreparedStatement对象

 

PreparedStatement可以防止SQL注入。

1.增

package com.zeng.lesson03;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TsetInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        try {
            conn = JdbcUtils.getConnection();
            //区别
            //使用?占位符代替参数

            String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`) values(?,?,?,?,?)";

            st = conn.prepareStatement(sql); //预编译sql先写sql,然后不执行
            //手动给参数赋值
            /*
                注意点:sql.Date    数据库     java.sql.Date()
                util.Date   Java    new Date().getTime() 获得时间戳

             */
            st.setInt(1,4);
            st.setString(2,"dongdong4");
            st.setString(3,"123456");
            st.setString(4,"77511593@qq.com");
            st.setDate(5,new java.sql.Date(new java.util.Date().getTime()));

            //执行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}

2.删

package com.zeng.lesson03;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        try {
            conn = JdbcUtils.getConnection();
            //区别
            //使用?占位符代替参数

            String sql = "delete from users where id = ?";

            st = conn.prepareStatement(sql); //预编译sql先写sql,然后不执行
            //手动给参数赋值
            st.setInt(1,4);
            //执行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("删除成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}

3.改

package com.zeng.lesson03;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        try {
            conn = JdbcUtils.getConnection();
            //区别
            //使用?占位符代替参数

            String sql = "update users set `NAME`=?  where id=?;";

            st = conn.prepareStatement(sql); //预编译sql先写sql,然后不执行
            //手动给参数赋值
            st.setString(1,"dongdong");
            st.setInt(2,4);
            //执行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("更新成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}

4.查

package com.zeng.lesson03;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where id = ?";

            st = conn.prepareStatement(sql);

            st.setInt(1,1);

            rs = st.executeQuery();

            if (rs.next()){
                System.out.println(rs.getString("NAME"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

5.防止sql注入

package com.zeng.lesson03;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.*;

public class Sql注入 {
    public static void main(String[] args) {
        login("wangwu","123456");
        //login(" ‘or‘1=1"," ‘or‘1=1");
    }
    public static void login(String username,String password){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            // PreparedStatement 防止:SQL注入的本质,把传递进来的参数当做字符
            // 假设其中存在转义字符,比如说‘会被直接转义
            String sql = "select * from users where `NAME`=? and `PASSWORD`=?";

            st = conn.prepareStatement(sql);
            st.setString(1,username);
            st.setString(2,password);

            rs = st.executeQuery();

            while (rs.next()){
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("password"));
                System.out.println("================");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

 

10.6 使用IDEA连接数据库

编写sql代码的地方

MySQL学习笔记

切换数据库

MySQL学习笔记

 

驱动

MySQL学习笔记

 

 

10.7 事务

 

要么都成功,要么都失败

ACID原则 原子性,一致性,隔离性,持久性

 

代码实现

  1. 开启事务conn.setAutoCommit(false);

  2. 一组业务完毕,提交事务

  3. 可以在catch语句中显示的定义回滚语句,但默认失败就会回滚

 

package com.zeng.lesson04;

import com.zeng.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestTransaction2 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st= null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            //关闭数据库自动提交,还会自动开启事务

            conn.setAutoCommit(false);

            String sql1 = "update account set money = money-100 where name = ‘A‘";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();

            int x = 1/0; //会报错

            String sql2 = "update account set money = money+100 where name = ‘B‘";
            st = conn.prepareStatement(sql2);
            st.executeUpdate();

            //业务完毕,提交事务
            conn.commit();
            System.out.println("成功");

        } catch (SQLException e) {
            //如果失败会默认回滚
            /*try {
                conn.rollback();  //如果失败则回滚事务
            } catch (SQLException ex) {
                ex.printStackTrace();
            }*/
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

 

 

10.8 数据库连接池

数据库连接--执行完毕--释放 ? 连接-释放 十分浪费系统资源 所以会有有连接池 池化技术:准备-些预先的资源,过来就连接预先准备好的 最小连接数: 10 最大连接数: 15 等待超时: 100ms 编写连接池,实现-个接口DataSource

 

开源数据源实现

DBCP

C3P0

Druid:阿里巴巴的

使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了!

 

BDCP

需要用到的

commons-dbcp-1.4

commons-pool-1.6

 

C3P0

 

需要用到的

c3p0-0.9.5.5

mchange-commons-java-0.2.19

 

结论

无论使用什么数据源,本质还是一样的,DataSource接口不会变,方法就不会变

MySQL学习笔记

上一篇:JS干货分享—-this指向


下一篇:数据库之MySQL其三