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 数据库字段的类型

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

  • smallint 较小的数据 2个字节

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

  • int 标准的整数 4个字节

  • bigint 较大的数据 8个字节

  • float 浮点数 4个字节

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

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

  1. 字符串
  • char    固定大小的字符串 0~255

  • varchar 可变字符串 0~65535 常用的变量String

  • tinytext 微型文本 2^8 - 1

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

  1. 时间日期(java.util.Date)
  • date YYYY-MM-DD 日期格式

  • time HH:mm:ss 时间格式

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

  • timestamp 时间戳 1970.1.1到现在的毫秒数!也比较常见

  • year 年份表示

  1. null
  • 没有值,未知

  • 注意:不要使用null进行运算,结果为null

1.3.4 数据库字段的属性

  1. Unsigned
  • 无符号的整数

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

  1. Zerofill
  • 0填充的

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

  1. Auto increment
  • 自增,自动在上一条记录的基础上+1(默认)

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

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

  1. Default
  • 设置默认的值

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

  1. 非空 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条件字句:

  1. 逻辑运算符:
运算符 语法 描述
and  && a and b   a && b 逻辑与,两个都为真,结果为真
or | a or b      a | b 逻辑或,有一个为真,结果为真
not   ! not a       !a 逻辑非, 真为假,假为真

尽量使用英文字母

  1. 模糊查询:比较运算符
运算符 语法 描述
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到任意个字符

  • _ : 代表一个字符

  1. 连表查询:

7种join理论:
image

2.4 MySQL函数

官网:MySQL :: MySQL 8.0 Reference Manual :: 12.1 Built-In Function and Operator Reference

2.4.1 常用函数
  1. concat
-- 作用:拼接字段
SELECT CONCAT('姓名:', name)
  1. distinct
-- 作用:去除SELECT查询出来的结果重复的数据,重复的数据只显示一条
SELECT DISTINCT column_name FROM table_name
  1. version
-- 作用:查看数据库版本
SELECT VERSION()
  1. @@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();

执行结果:!
image

查询,发现太慢,创建索引:

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步骤:

  1. 加载驱动:Class.forName()

  2. 连接数据库:DriverManager

  3. 获取执行sql的对象:Statement

  4. 获得返回的结果集:ResultSet

  5. 释放连接,关闭资源

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

posted @   zlonger  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示