MySQL
MySQL
一、初识MySQL
JavaEE:企业级Java开发 web
-
前端:(页面:展示,数据!)
-
后端:(连接点:连接数据库JDBC,连接前端【控制,控制试图跳转,和给前端传递数据】)
-
数据库:(存数据,Text,Excel,word)
只会写代码,学好数据库,基本混饭吃
操作系统,数据结构和算法!当一个不错的程序员!
离散数学,数字电路,体系结构,编译原理+实战经验。高级程序猿优秀的程序员
-
当今社会,最值钱的就是数据!
-
数据库是所有软件体系中最核心的存在!DBA
1.1 什么是数据库?
数据库:DB,DataBase
概念:数据仓库
作用:存储数据,管理数据。
1.2 数据库分类
-
关系型数据库:(SQL)
-
MySQL, Oracle, Sql Server, DB2, SQLlife
-
通过表和表之间,行和行之间的关系进行数据的存储
-
-
非关系型数据库:(NoSQL, Not Only SQL)
-
Redis, MongoDB
-
非关系型数据库,对象存储,通过对象的自身的属性来决定
-
数据库管理系统:(DBMS)
数据库的管理软件。
1.3 MySQL
1.3.1 MySQL简介
MySQL是一个关系型数据库管理系统
前世:MySQL AB
今生:属于Oracle旗下产品
优点:开源、免费、体积小、速度大
适用于:中小型网站、或者大型网站、集群!
1.3.2 数据库xx语言
-
DDL:数据定义语言(Data Definition Language)
-
DML:数据操作语言(Data Manipulation Language)
-
DQL:数据查询语言(Data Query Language)
-
DCL:数据控制语言(Data Control Language)
1.3.3 数据库字段的类型
- 数值
-
tinyint 十分小的数据 1个字节
-
smallint 较小的数据 2个字节
-
mediumint 中等大小的数据 3个字节
-
int 标准的整数 4个字节
-
bigint 较大的数据 8个字节
-
float 浮点数 4个字节
-
double 浮点数 8个字节(精度问题!)
-
decimal 字符串形式的浮点数 金融计算的时候,一般是使用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
1.3.4 数据库字段的属性
- Unsigned
-
无符号的整数
-
声明了该列不能声明为负数
- Zerofill
-
0填充的
-
不足的位数,使用0来填充。【例:int(3), 5 --- 005】
- Auto increment
-
自增,自动在上一条记录的基础上+1(默认)
-
通常用来设计唯一的主键,index,必须是整数类型
-
可以自定义设计主键自增的起始值和步长
- Default
-
设置默认的值
-
例:sex, 默认为男,如果不指定该列的值,则会有默认的值!
- 非空 Null not null
-
假如设置为not null, 如果不给它赋值,就会报错!
-
Null, 如果不填写值,默认就是null
1.3.5 数据库语句
1.创建数据库
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(10) NOT NULL COMMENT '姓名',
`pwd` VARCHAR(10) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` INT(1) NOT NULL DEFAULT 0 COMMENT '性别:0-女,1-男',
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
`address` VARCHAR(20) NOT NULL DEFAULT 'china' COMMENT '家庭住址',
`email` VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
2.查看数据库的创建语句
SHOW CREATE DATABASE 数据库名;
3.查看表的创建语句
SHOW CREATE TABLE 表名;
4.显示表的结构
DESC 表名;
1.3.6 数据库的存储引擎
-- 关于数据库引擎
/*
INNODB : 默认使用
MYISAM : 早些年使用的
*/
MYISAM | INNODB | |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持(表级锁) | 支持(行级锁) |
外键约束 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
表空间的大小 | 较小 | 较大,约为MYISAM的2倍 |
常规使用操作:
-
MYISAM : 节约空间,速度较快
-
INNODB : 安全性高,事务的处理,多表多用户操作
1.3.7 修改和删除数据表字段
修改:
-- 1.修改表名 : ALTER TABLE 旧表名 RENAME AS 新表明
ALTER TABLE project RENAME AS `project1`;
-- 2.增加表的字段 : ALTER TABLE 表名 ADD 字段名 列属性
ALTER TABLE project1 ADD age INT(11);
-- 3.修改表字段(列属性): ALTER TABLE 表名 MODIFY 列名 列属性 COMMENT 注释
ALTER TABLE project1 MODIFY age CHAR(1) COMMENT "年龄";
-- 4.修改表字段(重命名) : ALTER TABLE 表名 CHANGE 旧列名 新列名 列属性 COMMENT 注释
ALTER TABLE project1 CHANGE `age` `age1` INT(1);
-- 5.删除表的字段 : ALTER TABLE 表名 DROP 字段名
ALTER TABLE project1 DROP `age1`;
删除:
-- 删除表 : DROP TABLE IF EXISTS 表名
DROP TABLE IF EXISTS `project1`;
注意:
-
所有的创建和删除操作,尽量加上IF EXISTS,避免报错
-
MySQL大小写不敏感,但是尽量要大小写敏感(规范)!
-
字段名,表名:``
-
注释: -- /**/
constraint : 约束
二、MySQL数据管理
2.1 外键(了解)
**方法一:创建表的同时创建外键
-- 年级表
CREATE TABLE `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
`gradename` VARCHAR(20) NOT NULL COMMENT '年级名称',
PRIMARY KEY (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 学生表
-- 学生表的gradeid字段,要去引用年级表grade的gradeid字段
-- 1.定义外键 key `FK_gradeid`
-- 2.给这个key添加约束:constraint约束 执行引用 references引用
CREATE TABLE IF NOT EXISTS `student`(
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '学生id',
`name` VARCHAR(20) NOT NULL COMMENT '姓名',
`age` INT(10) NOT NULL COMMENT '年龄',
`gradeid` INT(10) NOT NULL COMMENT '年级id',
PRIMARY KEY (`id`),
KEY `FK_gradeid` (`gradeid`),
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`)
)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 哪个表(哪个字段)
以上的操作都是物理外键,数据库级别的外键,我们不建议使用!!!(避免数据库过多造成困扰!了解即可!)
最佳实践:
-
数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)
-
我们想使用多张表的数据,想使用外键(程序去实现,应用层去解决!)
2.2 DML语言(重要)
数据库的意义: 数据存储,数据管理!
DML: 数据操作语言(Data Manipulation Language)
2.2.1 添加
INSERT:
INSERT INTO 表名([字段1],[字段2]...) values(值1, 值2 ...);
2.2.2 修改
UPDATE:
UPDATE 表名 SET 列名1=值1, 列名2=值2 ... WHERE [条件]
操作符 | 含义 | |
---|---|---|
= | 等于 | |
<> != | 不等于 | |
> | ||
>= | ||
< | ||
<= |
2.2.3 删除
DELETE:
DELETE FROM 表名 [WHERE 列名=值]
TRUNCATE:
作用:完全清空一个数据库表,表的结构和索引约束不会变!
TRUNCATE TABLE 表名
DELETE和TRUNCATE的区别:
-
相同点:
- 都用来删除表数据
-
不同点:
-
TRUNCATE 重新设置自增列,计数器会归零
-
TRUNCATE 不会影响事务
-
DELETE删除的问题,重启数据库,现象:
-
InnoDB 自增列会从1开始(存在内存当中,断电即失)
-
MyISAM 继续从上一个自增量开始 (存在文件当中,不会丢失)
2.3 DQL
DQL: 数据查询语言(Data Querary Language)
数据库最核心的语言
SELECT完整语法:
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}]; -- 指定查询的记录从哪条至哪条
MySQL书写顺序:
->select
->distinct
->from
->join
->on
->where
->group by
->having
->order by
->limit
MySQL执行顺序:
->from
->on
->join
->where
->group by(开始使用select中的别名,后面的语句中都可以使用别名)
->sum、count、max、avg
->having
->select
->distinct
->order by
->limit
注意:[]代表可选的,{}代表必选的
WHERE条件字句:
- 逻辑运算符:
运算符 | 语法 | 描述 |
---|---|---|
and && | a and b a && b | 逻辑与,两个都为真,结果为真 |
or | | a or b a | b | 逻辑或,有一个为真,结果为真 |
not ! | not a !a | 逻辑非, 真为假,假为真 |
尽量使用英文字母
- 模糊查询:比较运算符
运算符 | 语法 | 描述 |
---|---|---|
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到任意个字符
-
_ : 代表一个字符
- 连表查询:
7种join理论:
2.4 MySQL函数
官网:MySQL :: MySQL 8.0 Reference Manual :: 12.1 Built-In Function and Operator Reference
2.4.1 常用函数
- concat
-- 作用:拼接字段
SELECT CONCAT('姓名:', name)
- distinct
-- 作用:去除SELECT查询出来的结果重复的数据,重复的数据只显示一条
SELECT DISTINCT column_name FROM table_name
- version
-- 作用:查看数据库版本
SELECT VERSION()
- @@auto_increment_increment
-- 作用:查询自增的步长
SELECT @@auto_increment_increment
-- 数学运算
SELECT ABS(-8) -- 8 绝对值
SELECT CEILING(9.4) -- 10 向上取整 ceiling 天花板
SELECT FLOOR(9.4) -- 9 向下取整 floor 地板
SELECT RAND() -- 返回一个0~1之间的随机数
SELECT SIGN(0) -- 判断一个数的符号 负数返回-1, 整数返回1, 0返回0
-- 字符串函数
SELECT CHAR_LENGTH('励精图治,文治武功') -- 返回字符串的长度
SELECT CONCAT('三', '黄', '五', '帝') -- 拼接字符串
SELECT INSERT('我爱编程HelloWorld',1,2,'超级热爱') -- 从某个位置开始替换某个字符串
SELECT LOWER('Longer') -- 转为小写字母
SELECT UPPER('Longer') -- 转为大写字母
SELECT INSTR('zifuchuan','ua') -- 返回第一次出现字串的索引
SELECT REPLACE('方向比努力重要','方向','天赋') -- 替换出现的指定字符串
SELECT SUBSTR('今天又是充满希望的一天', 5,4) -- 截取字符串(源字符串,截取的位置,截取的长度)
SELECT REVERSE('为所欲为') -- 反转
-- 时间和日期函数
SELECT CURRENT_DATE() -- 2022-01-18 获取当前日期
SELECT CURDATE() -- 2022-01-18 获取当前日期
SELECT NOW() -- 2022-01-18 14:38:40 获取当前时间
SELECT LOCALTIME() -- 2022-01-18 14:39:14 获取本地时间
SELECT SYSDATE() -- 2022-01-18 14:39:36 获取系统时间
SELECT YEAR(NOW()) -- 2022 获取年
SELECT MONTH(NOW())
SELECT DAY(NOW())
SELECT HOUR(NOW())
SELECT MINUTE(NOW())
SELECT SECOND(NOW())
-- 系统
SELECT SYSTEM_USER()
SELECT USER()
SELECT VERSION()
2.4.2 聚合函数
COUNT(字段),COUNT(*),COUNT(1)的区别:
-
COUNT(字段):会忽略所有的null值
-
COUNT(*):不会忽略null值,本质-计算行数
-
COUNT(1):不会忽略null值,本质-计算行数
函数 | 说明 |
---|---|
COUNT() | 计算 |
SUM() | 求和 |
AVG() | 求平均数 |
MAX() | 求最大值 |
MIN() | 求最小值 |
2.4.3 MD5加密
SELECT MD5('12345')
三、事务
事务:要么都成功,要么都失败!
3.1 事务原则:ACID原则
-
原子性(Atomicity): 要么都成功,要么都失败!
-
一致性(Consistency): 事务前后的数据完整性要保持一致,1000
-
隔离性(Isolation): 事务的隔离性时多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其它事务的操作数据所干扰,事务之间要相互隔离。
-
持久性(Durability): 事务提交,事务一旦提交则不可逆,被持久化到数据库中!
3.2 事务的隔离级别
-
脏读: 指一个事务读取了另外一个事务未提交的数据。
-
不可重复度: 在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)
-
虚读(幻读): 是指一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
事务:
-- =========================事务=========================
-- MySQL是默认开启事务自动提交的
SET autocommit = 0; -- 关闭
SET autocommit = 1; -- 开启(默认的)
-- 手动处理事务
SET autocommit = 0;
-- 事务开启
START TRANSACTION; -- 标记一个事务的开始,从这个之后的sql都在同一个事务内。
INSERT xx
INSERT xx
-- 提交:持久化(成功!)
COMMIT;
-- 回滚:回到原来的样子(失败!)
ROLLBACK;
-- 事务结束
SET autocommit = 1;
-- 了解
SAVEPOINT 保存点名 -- 设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名 -- 撤销保存点
MySQL模拟转账:
-- 转账
CREATE DATABASE shop CHARACTER utf8 COLLATE utf8_general_ci
USE shop
CREATE TABLE `account`(
`id` INT(10) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(10) 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减500
UPDATE account SET money = money + 500 WHERE `name` = 'B'; -- B加500
COMMIT; -- 提交事务,就被持久化了!
ROLLBACK; -- 回滚
SET autocommit = 1; -- 恢复自动提交
四、索引
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
提取句子主干,就可以得到索引的本质:索引是数据结构。
4.1 索引的分类
在以一个表中,主键索引只能有一个,唯一索引可以有多个
-
主键索引(PRIMARY KEY)
- 唯一的标识,主键不可重复,只能有一个列作为主键。
-
唯一索引(UNIQUE KEY)
- 避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引。
-
常规索引(KEY/INDEX)
- 默认的,index,key关键字来设置。
-
全文索引(FULLTEXT)
-
在特定的数据库引擎下才有,MYISAM
-
快速定位数据。
-
-- 索引的使用
-- 1、在创建表的时候给字段增加索引
-- 2、创建完表之后,增加索引
-- 3、CREATE INDEX 索引名 ON 表名(字段名)
ALTER TABLE 表名 ADD FULLTEXT INDEX 列名(索引名)
-- 显示所有的索引信息
SHOW INDEX FROM 表名
-- EXPLAIN 分析sql执行的状况
EXPLAIN SELECT * FROM 表名; -- 非全文索引
EXPLAIN SELECT * FROM student WHERE MATCH(`studentName`) AGAINST('刘');
4.2 测试索引
创建表:
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 NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT 'app用户表';
插入100万条数据:
-- 插入100万条数据
-- delimiter $$ : 定义分隔符,MySQL默认的分隔符为';',而函数当中可能会用到分号,
-- 为了避免冲突,需要另外定义分隔符。
DELIMITER $$
-- 函数:mock_date():模拟插入数据函数
CREATE FUNCTION mock_date() 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), '123456789@qq.com', CONCAT('13',FLOOR(RAND()*((999999999-100000000)+100000000))), FLOOR(RAND()*2), UUID(), FLOOR(RAND()*100));
SET i = i+1;
END WHILE;
RETURN i;
END $$
-- 将分隔符切换回去
DELIMITER ;
-- 可能遇到的问题:
-- 其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。如果我们开启了 bin-log, 我们就必须为我们的function指定一个参数。
-- 在MySQL中创建函数时出现这种错误的解决方法:
SET global log_bin_trust_function_creators=TRUE;
-- 执行函数
SELECT mock_date();
执行结果:!
查询,发现太慢,创建索引:
SELECT * FROM app_user WHERE `name` = '用户13'; -- Query time : 1.086s
EXPLAIN SELECT * FROM app_user WHERE `name` = '用户13'; -- EXPLAIN 查看sql执行结果
-- 查询时间太久,添加索引
-- 创建索引 索引名_表名_index
CREATE INDEX nameind_app_user_index ON app_user(`name`);
-- 查看索引
SHOW INDEX FROM app_user;
-- 创建完索引之后,再进行查询,查询时间大大提高:1.086s --> 0.036s
SELECT * FROM app_user WHERE `name` = '用户13'; -- Query time : 0.036s
EXPLAIN SELECT * FROM app_user WHERE `name` = '用户13'; -- EXPLAIN 查看sql执行结果
索引在小数据量的时候,用处不大;但在大数据量的时候,区别十分明显!
索引命名规范:
主键索引名为pk_字段名;
唯一索引名为uk_字段名;
普通索引名则为idx_字段名。
说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。
4.3 索引原则
-
索引并不是越多越好
-
不要对经常变动的数据加索引
-
小数据量的表不需要加索引
-
索引一般加在常用来查询的、不变的字段上
索引的数据结构:
Hash类型的索引
BTree:InnoDB的默认数据结构
阅读文章: http://blog.codinglabs.org/articles/theory-of-mysql-index.html
五、权限管理和备份
5.1 用户管理
-- 创建用户
CREATE USER 用户名 IDENTIFIED BY '密码'
-- 修改密码(当前用户)
SET PASSWORD = PASSWORD('密码')
-- 修改密码(指定用户)
SET PASSWORD FOR 用户名 = PASSWORD('密码')
-- 重命名
RENAME USER old_用户名 TO new_用户名
-- 用户权限 ALL PRIVILEGES 全部的权限,库.表
-- ALL PRIVILEGES 除了给别人授权,其它都能够干
GRANT ALL PRIVILEGES ON *.* TO 用户名
-- 查询权限
SHOW GRANTS FOR 用户名 -- 查看指定用户的权限
SHOW GRANTS FOR root@localhost
-- ROOT 用户权限: GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
-- 撤销权限 REVOKE 哪些权限, 在哪个库撤销, 给谁撤销
REVOKE ALL PRIVILEGES ON *.* FROM 用户名
-- 删除用户
DROP USER 用户名
5.2 数据备份
为什么要备份?
-
保证重要的数据不丢失
-
数据转移
MySQL备份方式:
-
直接拷贝物理文件
-
数据库连接工具进行导出备份
-
使用命令行导出 mysqldump 命令行使用
mysqldump -hlocalhost -uroot -proot123 test user > D:/a.sql
-- 格式:mysqldump -h主机 -u用户名 -p密码 数据库名 表名 > 物理磁盘位置/文件名
-- 导出多张表
-- 格式:mysqldump -h主机 -u用户名 -p密码 数据库名 表1 表2 表3 > 物理磁盘位置/文件名
导入sql文件到数据库
-- 1.命令行登录数据库
-- 2.USE 数据库
-- 3.source sql文件位置
六、规范数据库设计
6.1 为什么需要设计
当数据库比较复杂的时候,我们就需要设计了!
-
糟糕的数据库设计:
-
数据冗余,浪费空间
-
数据库插入和删除都会麻烦、异常【屏蔽使用武力外键】
-
程序的性能差
-
-
良好的数据库设计:
-
节省内存空间
-
保证数据库的完整性
-
方便我们开发系统
-
软件开发中,关于数据库的设计:
-
分析需求:分析业务和需要处理的数据库的需求
-
概要设计:设计关系图【E-R图】
设计数据库的步骤:(个人博客)
-
收集信息,分析需求
-
标识实体
6.2 三大范式
-
第一范式(1NF):
- 原子性:保证每一列不可再分
-
第二范式(2NF):
-
前提:满足第一范式
-
每张表只描述一件事情
-
-
第三范式(3NF):
-
前提:满足第一范式和第二范式
-
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关
-
规范性和性能的问题:
关联查询的表不得超过三张表
-
考虑商业化的需求和目标,(成本,用户体验!)数据库的性能更加重要
-
在规范性能的问题的时候,需要适当的考虑一下规范性!
-
故意给某些表增加一些冗余的字段。(从多表查询变为单表查询)
-
故意增加一些计算列(从大数据量降低为小数据量的查询:索引)
为什么需要数据规范化?
-
信息重复
-
更新异常
-
插入异常
-
删除异常
七、JDBC(重点)
SUN公司为了简化开发人员对数据库的统一操作,提供了一个(Java操作数据库的)规范,俗称JDBC,这些规范的实现由具体的厂商去实现。
对于开发人员来说,我们只需要掌握JDBC接口的操作即可!
7.1 JDBC步骤
JDBC步骤:
-
加载驱动:Class.forName()
-
连接数据库:DriverManager
-
获取执行sql的对象:Statement
-
获得返回的结果集:ResultSet
-
释放连接,关闭资源
package cn.com.longer;
import java.sql.*;
/**
* JDBC demo
*/
public class JdbcFirstDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.加载程序
Class.forName("com.mysql.cj.jdbc.Driver"); // 固定写法,加载驱动
// 2.用户信息和url
// 固定写法: useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
// 3.连接成功,数据库对象
Connection connection = DriverManager.getConnection(url, username, password);
// 4.执行SQL的对象
Statement statement = connection.createStatement();
// 5.编写sql
String sql = "SELECT * FROM grade";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("gradeid:"+resultSet.getObject("gradeid"));
System.out.println("gradename:"+resultSet.getObject("gradename"));
System.out.println("================================");
}
// 6.释放资源
resultSet.close();
statement.close();
connection.close();
}
}
7.2 Statement对象
Statement为sql执行平台,用于向数据库发送SQL语句。
-
executeQuery() : 执行查询语句,返回ResultSet对象
-
executeUpdate() : 执行增、删、改语句,返回类型为int,为执行影响的行数
-
execute() : 执行所有的语句
7.3 SQL注入
sql存在漏洞,会被攻击导致数据泄露,SQL会被拼接or.
7.4 PreparedStatement对象
PreparedStatement对象,占位符的形式,可以防止SQL注入!
package cn.com.longer;
import java.sql.*;
/**
* 预编译执行平台
*/
public class JdbcSecondDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.加载程序
Class.forName("com.mysql.cj.jdbc.Driver"); // 固定写法,加载驱动
// 2.用户信息和url
// 固定写法: useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
// 3.连接成功,数据库对象
Connection connection = DriverManager.getConnection(url, username, password);
// 4.编写sql
String sql = "SELECT * FROM grade WHERE gradeid = ? AND gradename = ?";
// 5.创建预编译执行平台 preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 6.传参
preparedStatement.setInt(1, 1);
preparedStatement.setString(2, "大一");
// 4.执行SQL
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.println("gradeid:"+resultSet.getObject("gradeid"));
System.out.println("gradename:"+resultSet.getObject("gradename"));
System.out.println("================================");
}
// 6.释放资源
resultSet.close();
preparedStatement.close();
connection.close();
}
}
7.5 数据库连接池
数据库连接---执行完毕---释放
连接---释放 十分浪费系统资源
池化技术: 准备一些预先的资源,过来就连接预先准备好的。
DBCP、C3P0、Druid
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?