学习思路:对照sqlyog可视化历史记录查看SQL
固定的语法或关键字必须记住
初识mysql 如何删除数据库数据
sc delete mysql
删除数据库数据
1.1sqlyog软件基本使用
每一个sqlyog的执行操作本质上是一段sql语句
1.2命令行操作
链接数据库 mysql -uroot -p密码
exit 退出连接
–是注释
所有的语句都使用分号结尾
flush privileges; 刷新权限
1.1基本查看动作
show databases; 查看所有数据库
use 数据库名 切换数据库
show tables --查看数据库中的所有表
describe --查看数据库中的所有表
1.2创建基本操作
create database westos;
//创建一个名叫westos的数据库
1.3数据库 xxx语言
DDL 数据库定义语言
DML 数据库操作语言
DQL 数据库查询语言
DCL 数据库控制语言
2.操作数据库
操作数据库>操作数据库中的表>操作数据库表中的数据
mysql不区分大小写
2.1操作数据库(了解就好)
1.创建数据库
CREATE DATABASE IF NOT EXISTS westos;
2.删除数据库
DROP DATABASE IF EXISTS hello;
3.使用数据库
USE school
;
如果表名是一个特殊字符则需要带``
4.查看所有的数据库
SHOW DATABASES;
对比sqlylg的可视化操作
2.2数据库的列类型
数值
从小到大
- tinyint 1个字节
- smallint 2个字节
- mediumint 中等大小的数据 3个字节
- int 标准的整数 4个字节常用
- bigint 较大的数据 8个字节
- float 浮点数 4个字节
- double 浮点数 8个字节(精度问题)
- decimal 字符串形式的浮点数 金融计算的时候一般使用
字符串
- char 字符串固定大小 0-255
- varchar 可变字符串 0-65535 常用的变量 对标java String
- tinytest 微型文本 2 8 − 1 2^8-1 28−1
- test 文本串 2 16 − 1 2^{16}-1 216−1 保存大文本
时间日期
类似java,util.Data
- data YYYY-MM-DD 日期
- HH:mm:ss 时间格式
- datatime YYYY-MM-DD HH:mm:ss 最常用的时间格式
- timestamp 时间戳 1970.01.01 到现在的毫秒数 也较为常用
- year 年份表示
null
没有值,位置
2.3数据库的字段属性==(重点)==
Unsigned:
- 无符号的整数
- 声明了该列不能声明为负数
zerofill:
- 0填充的
- 不足的位数使用0来填充
自增:
- 通常理解为自动在上一条记录的基础上加1(默认)
- 通常用来设置唯一的主键 index 并且必须是整数类型
- 可以自定义设置主键的起始值和步长
非空 NULL not null
- 假设设置为not null,如果不给它赋值,就会报错
- 如果不填写值,默认是null
默认:default
- 设置默认值
- 如果不改变该列的值,则会有默认的值
拓展
2.4创建数据库表
注意点表的名称和字段尽量使用``
起来
字符串使用单引号括号起来
所有语句前加, 最后一个语句不加
PRIMARY KEY主键,一般一个表只有一个唯一的主键
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 '出生日期',
`address` VARCHAR (100) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
格式
CREATE TABLE IF NOT EXISTS `表名`(
`字段名` 列类型 【属性】【索引】【注释】,
`字段名` 列类型 【属性】【索引】【注释】,
...
`字段名` 列类型 【属性】【索引】【注释】,
)【表类型】【表字符集设置】
常用命令
SHOW CREATE DATABASE school;
查看创建数据库的语句
SHOW CREATE TABLE student;
查看创建表的语句
DESC student;
查看表的结构
2.5数据表的类型
INNODB 默认使用
MYISAM 早些年使用
MYISAM | INNODB | |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
外键 | 不支持 | 支持 |
全文索引 | 支持 | 支持 |
表空间的大小 | 较小 | 较大,约为MYISAM的两倍 |
- MYSIAM 节约空间,速度较快
- INNODB 安全性高,事务的支持,多表多用户操作
物理空间存在的位置
所有的数据库文件都存在data文件下
本质还是文件的存储
MYSQL 引擎在物理文件上的区别
-
innoDB 在数据库表中只有一个*.frm文件,以及上级目录下的ibdata1文件
-
MYSIAM对应文件
*.frm | 表结构的定义文件 |
---|---|
*.MYD | 数据文件(data) |
*.MYI | 索引文件(index) |
设置数据库表的字符集编码
DEFAULT CHARSET=utf8
不设置的话,会是mysql默认的字符编码latin1
在my.ini中配置默认的编码
2.6修改删除表
修改
- 修改表名
ALTER TABLE student RENAME AS teacher;
第一个是旧表名,第二个是新表名 - 增加表的字段
ALTER TABLE teacher ADD age INT(11);
add 一个age字段 - 修改表的字段
ALTER TABLE teacher MODIFY age VARCHAR(11);
将age的字段修改为VAECHAR(11); --修改约束 - 字段重命名
ALTER TABLE teacher CHANGE age age1 INT(1);
- 删除表的字段
ALTER TABLE teacher DROP age;
- 给创建表的字段设置默认值
ALTER TABLE student ALTER COLUMN `name` SET DEFAULT '东东';
删除
- 删除表的字段
ALTER TABLE teacher DROP age;
所有的创建和删除操作尽量加上判断,以免报错
注意点
- 所有字段名使用
``
包裹 - 注释 - - 或者 /* */
- sql关键字大小写不敏感,建议大家写小写
- 所有的符号全部用英文
3MySQL数据管理
3.1外键(了解即可)
方式一,在创建表的时候给主键增加约束
-- 创建grade
··
-- 学生表的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 '出生日期',
`address` VARCHAR (100) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
`gradeid` INT(10) NOT NULL COMMENT '学生的年级',
PRIMARY KEY(`id`),
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 哪个表(哪个字段);
以上的操作都是物理外键,数据库级别的外键,(避免数据库过多造成困扰)
最佳实践
- 数据库就是单纯的表,只用来存放数据,行代表数据,列代表字段
- 我们想使用多张表的数据,程序去实现
- 了解即可,避免使用外键
3.2DML语言(全部记住,背下来)
数据库的意义:数据存储跟数据管理
DML语言: 数据操作语言
- insert
- update
- delete
3.3添加
– 由于主键自增,我们可以省略主键
– insert into 表名(字段1,字段2,字段3) values(‘值1’,‘值2’,‘值3’)
INSERT INTO `grade`(`gradename`) VALUES('大四');
效果图:
– 不写字段就会一一匹配
– 一般写插入语句一定要数据可字段一一对应
INSERT INTO `grade` VALUES('大四');
– 输入多个字段
INSERT INTO `grade`(`gradename`) VALUES('大一'),('大二');
注意事项:
1字段和字段之间使用,隔开
2字段是可以省略的,但是后面的值要一一对应
3.4修改
update 修改谁 (条件) set 原来的值=新值,… 条件
UPDATE `student` SET `name`='李佳乐' WHERE id = 1;
修改多个属性:用,隔开
修改id等于1的name
不加where会全部进行修改
条件:where 字句 运算符 id等于某个 值,大于某个值,在某个区间内修改…
操作符 | 意义 | 范围 | 结果 |
---|---|---|---|
= | 范围 | 5=6 | false |
<> 或者!= | 不等于 | 5!=6 | true |
> | |||
>= | |||
< | |||
<= | |||
between…and… | 在某个范围内闭合区间 | ||
and | && | ||
or | || |
用and和or可以进行多个条件判断
- 尽量带着
``
- 条件,删选的条件,如果没有指令则会修改所有的列
- value是一个具体的值,也可以是一个变量
- 新值不一定是一个具体的值,也可以是一个变量(时间CURRENT_TIME)
- 多个设置的属性之间,使用英文逗号隔开
3.5删除
delete命令
delete from 表名 where 条件
DELETE FROM `student` WHERE id=1;
truncate命令
完全清空一个数据库表,表的结构和索引约束不会变
delete 和truncate区别
相同点:都能删除数据,都不能删除表结构
不同:
- truncate 重新设置自增列 计数器会归零
- truncate 不会影响事务
-- 创建一个测试表
CREATE TABLE `test` (
`id` INT(4) NOT NULL AUTO_INCREMENT,
`coll` VARCHAR(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入几个测试数据
INSERT INTO test(coll) VALUES('row1'),('row2'),('row3');
-- 删除表数据(不带where条件的delete)
DELETE FROM test;
-- 结论:如不指定Where则删除该表的所有列数据,自增当前值依然从原来基础上进行,会记录日志.
-- 删除表数据(truncate)
TRUNCATE TABLE test;
-- 结论:truncate删除数据,自增当前值会恢复到初始值重新开始;不会记录日志.
-- 同样使用DELETE清空不同引擎的数据库表数据.重启数据库服务后
-- InnoDB : 自增列从初始值重新开始 (因为是存储在内存中,断电即失)
-- MyISAM : 自增列依然从上一个自增数据基础上开始 (存在文件中,不会丢失)
4、DQL查询数据(最重点)
select 语法
4.1DQL
Data Query Language 数据查询语言
- 所有的查询操作都用到它,Select
- 简单的查询,复杂的查询他都能做到
- 数据库中最核心最重要使用频率最高的语言
4.2指定查询字段
– select 字段 from 表
查询全部年级
SELECT * FROM table;
查询指定字段
SELECT 字段 FROM table;
给结果起一个名字,列名字和表名都可以重命名
SELECT 字段 As 字段 FROM table As table2;
函数 Concat(a,b)
在要查询的b前面追加a,
SELECT CONCAT('姓名:',studentname) AS 新名字 FROM student;
效果图:
去重复 distinct
SELECT DISTINCT `studentno` FROM result;
去除重复的数据,只显示一条
查看系统版本(函数)
SELECT VERSION();
计算(表达式)
SELECT 100*3-1 AS 计算结果;
查询自增步长(变量)
SELECT @@auto_increment_increment;
让查询出来的值+1
SELECT `studentno`,`studentresult`+1 FROM result;
4.3 where条件字句
作用:检索数据中符合条件的值
搜索的条件由一个或者多个表达式组成 结果 布尔值
逻辑运算符
运算符 | 语法 | 描述 |
---|---|---|
and && | a and b a&&b | 逻辑与 |
or || | a or b a||b | 逻辑或 |
Not ! | not a !a | 逻辑非 |
尽量使用英文字母
实例:
SELECT studentno,`studentresult` FROM result WHERE `studentresult`>=95 AND `studentresult`<=100;
使用between and
SELECT studentno,`studentresult` FROM result WHERE `studentresult` BETWEEN 95 AND 100;
同理可以使用其他逻辑运算符
模糊查询(重点) 比较运算符
运算符 | 语法 | 描述 |
---|---|---|
IS NULL | a is null | 如果操作符为NULL,结果为真 |
IS NOT NULL | a is not null | 如果操作符为not null,结果为真 |
between and | 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
– like结合 %(代表0到任意个字符) _(一个字符)
– 查询姓张的同学
SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '张%';
– 查询姓张的后面只有一个字的同学
SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '张_';
同理查询两个字的加两根 _
例子 in
不能用like
– 查询1000 1001 号学员
SELECT `studentno`,`studentname` FROM student WHERE `studentno` IN (1000,1001);
– 查询在北京朝阳的学员
SELECT `studentno`,`studentname`,`address` FROM student WHERE address IN ('北京朝阳');
例子 null 和 not null
查询identitycard为空的学员
SELECT `studentno`,`studentname`,`address`,`identitycard` FROM student WHERE `identitycard` IS NULL ;
4.4连表查询
JOIN 对比
例子 inner join – left join – right join
join(连接的表) on (判断查询) 连接查询
where 等值查询
-- 查询参加了考试的同学(学号,姓名,科目编号,分数)
SELECT * FROM student;
SELECT * FROM result;
/*
思路
1、分析需求,分析查询的字段来自哪种表,(连接查询)
2、确定使用哪种查询?7种。
确定交叉点(这两个表中哪个数据是相同的)
判断条件:学生表中的studentno = 成绩表中的 studentno
*/
SELECT s.`studentno`,`studentname`,`subjectno`,`studentresult`
FROM student AS s
INNER JOIN result AS r
on s.`studentno`=r.`studentno`
操作 | 描述 |
---|---|
inner join | 如果表中至少有一个匹配,就返回行 |
left join | 即使右表中没有匹配,也会返回值 |
right join | 会从右表中返回所有值,即使左标中没有匹配 |
- left join以左表为基准,全部写入,然后再去右表中查询,右表中如果没有值则记为null;
- right join同理
- inner join是两表满足条件才会显示
连表查询三个表
SELECT s.`studentno`,studentname,`subjectname`,studentresult
FROM student s
RIGHT JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` s1
ON r.`subjectno`=s1.`subjectno`
假设存在多张表,先查询两张表,再查寻多张表
自连接
核心:将自己的表和自己的表连接,一张表拆为两张一样的表即可。
SELECT a.`categoryname` AS '父栏目', b.`categoryname` AS '子栏目'
FROM `category` AS a
LEFT JOIN `category` AS b
ON b.`pid`=a.`categoryid`;
4.5 分页和排序
排序
– order by 升序ASC 降序DESC
– order by 通过哪个字段排序,怎么排
排序例子
SELECT s.`studentno`,studentname,`subjectname`,studentresult
FROM student s
RIGHT JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` s1
ON r.`subjectno`=s1.`subjectno`
ORDER BY `studentresult` DESC
降序排
分页 limit
– 为什么要分页?
– 缓解数据库压力。给人更好的体验(瀑布流)
limit 起始值 页面的大小
(n-1)*pagesize,pagesize
4.6子查询
where(这个值是计算出来的)
本质:在where语句中嵌套一个子查询语句
-- 分数不小于80分的学生的学号和姓名
SELECT `studentno` , `studentname`
FROM student
WHERE studentno = ANY(
SELECT `studentno`
FROM result
WHERE result.`studentresult`>=80
)
5、Mysql函数
5.1常用函数(并没有那么常用)
1数学运算
-- 绝对值
SELECT ABS(-8)
-- 向上取整
SELECT CEILING(9.4)
-- 向下取整
SELECT FLOOR(9.4)
-- 随机数,返回0-1的随机数
SELECT RAND()
-- 判断一个数的符号 负数返回-1 正数返回1
SELECT SIGN(-10)
-- 字符串函数
-- -- 返回字符串长度
SELECT CHAR_LENGTH('即使再小的帆也能远航')
-- -- 拼接字符串
SELECT CONCAT('我','爱','你们')
-- -- 查询,替换
SELECT INSERT('我爱编程helloworld',1,2,'超级热爱')
-- -- 转小写字母
SELECT LOWER('XIAOLIPLUM')
-- -- 转大写字母
SELECT UPPER('xiaoliplum')
-- -- 返回第一次出现子串的索引
SELECT INSTR('xiaolipulm','p')
-- -- 替换出现的指定字符串
SELECT REPLACE('坚持就能成功','坚持','努力')
-- -- 截取字符串
SELECT SUBSTR('坚持就能成功',4,6)
-- -- 反转字符串
SELECT REVERSE('坚持就能成功')
-- 时间跟日期函数(记住)
-- -- 获取当前日期
SELECT CURRENT_DATE()
-- -- 获取当前日期
SELECT CURDATE()
-- -- 获取当前时间
SELECT NOW()
-- -- 获取本地时间
SELECT LOCALTIME()
-- -- 获取系统时间
SELECT SYSDATE()
SELECT ...(NOW()) 可以获取现在的年月日时间
-- 版本号
SELECT VERSION()
5.2聚合函数(常用)
函数名称 | 描述 |
---|---|
count() | 计数 |
sum() | 求和 |
avg() | 平均值 |
max() | 最大值 |
min() | 最小值 |
5.3分组以及过滤
-- 查询不同课程的平均分,最高分,最低分
-- 核心 根据不同的课程分组
SELECT subjectname,AVG(`studentresult`),MAX(`studentresult`),MIN(`studentresult`)
FROM result r
INNER JOIN `subject` sub
ON r.`subjectno`=sub.`subjectno`
GROUP BY r.subjectno
5.4拓展MD5数据库级别加密
UPDATE testmd5 SET pwd=MD5(pwd);
对用户传进来的密码进行加密,与存储在数据库中的md5加密后的密码进行比对
5.5select总结
select 去重 要查的字段 from 表(注意:表和字段可以取别名)
xxx join 要连接的表 on 等值判断
where (具体的值,子查询语句)
group by (通过字段来分组)
Having (过滤后的分组信息,条件和where是一样的,位置不同)
order by (通过哪个字段进行排序)
limit startindex,pagesize
业务层面
6事务
6.1什么是事务?
1、A 1000 B 200
2、A给B转账200 A->800
3、B收到 b->400
将一组sql放在一个批次中去执行
事务原则 原子性 一致性 隔离性 持久性 (脏读,换读)
原子性
两个步骤一起成功或者一起失败,不能只发生其中一个动作
一致性
事务前后数据的完整性要保持一直
持久性
事务一旦提交不可逆,持久化到数据库
隔离性
事务的隔离性是指多个用户并发访问数据库的时候,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,事物之间要相互隔离。
隔离导致的一些问题
1 脏读
指一个事务读取了另一个事务未提交的数据
2 不可重复读
在一个事务内读取表中的某一行数据,多行数据读取结果不同
3 幻读
当读的时候,插入一条id=5的数据,没有读出新插入的id=5的数据,但是插入id=5数据的时候报错。
6.2执行事务
-- mysql 是默认开启事务自动提交的
SET autocommit =0 ; //关闭
SET autocommit =1 ; //执行
-- 手动处理事务
-- 关闭自动提交
SET autocommit=0;
-- 事务开启
START TRANSACTION -- 标记一个事务 从这个之后的sql 都在同一事务内
-- 如果成功,提交
COMMIT
-- 如果失败,回滚,回到原来的样子
ROLLBACK
-- 事务结束
-- 开启自动提交
SET autocommit=1;
SAVEPOINT 保存点名 设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点
例子
-- 模拟转账
SET autocommit= 0 ; -- 关闭自动提交
START TRANSACTION -- 开启一个事务
UPDATE account SET money=money-500 WHERE `name` = 'A'
UPDATE account SET money=monney+500 WHERE `name` = 'B'
COMMIT; -- 提交,事务一旦提交就被持久化了
ROLLBACK;-- 回滚
SET autocommit=1; -- 恢复默认值
7、索引
mysql官方对索引的定义为:索引是帮助mysql高效获取数据的数据结构。
索引的本质:数据结构
7.1索引的分类
在一个表中,主键索引只能有一个,唯一索引可以有多个
- 主键索引 primary key
- 唯一的标识,主键不可重复,只能有一个列作为主键
- 唯一索引 unique key
- 避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引
- 常规索引 key / index
- 默认的,index,key关键字设置
- 全文索引 full text
- 在特定的数据库引擎下,才有
- 快速定位数据
索引的使用
1、在创建表的时候给字段增加索引
2、创建完毕后,增加索引
显示所有索引信息
增加一个全文索引
ALTER TABLE `student` ADD FULLTEXT INDEX `studentname` (`studentname`);
前面studentname是索引名,后面studentname是列名
CREATE INDEX id_app_user_name ON app_user(`name`)
create index 索引名 on 表(字段)
基础语法
SHOW INDEX FROM student;
-- explain 分析sql执行的状况
EXPLAIN SELECT * FROM student ; -- 常规索引,非全文索引,查了3rows
EXPLAIN SELECT * FROM student WHERE MATCH(studentname) AGAINST('刘');
7.2测试索引
数据生成代码
CREATE TABLE `app_user` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) DEFAULT '',
`eamil` VARCHAR(50) NOT NULL,
`phone` VARCHAR(20) DEFAULT '',
`gender` TINYINT(4) UNSIGNED DEFAULT '0',
`password` VARCHAR(100) NOT NULL DEFAULT '',
`age` TINYINT(4) DEFAULT NULL,
`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-- 插入100万数据.
SET GLOBAL log_bin_trust_function_creators=1; -- 开启创建函数功能
/*
第一个语句 delimiter 将 mysql 解释器命令行的结束符由”;” 改成了”$$”,
让存储过程内的命令遇到”;” 不执行
*/
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`,`eamil`,`phone`,`gender`)VALUES(CONCAT('用户',i),'19224305@qq.com','123456789',FLOOR(RAND()*2));
SET i=i+1;
END WHILE;
RETURN i;
END;$$
SELECT mock_data()$$ -- 执行此函数 生成一百万条数据
测试
SELECT * FROM app_user WHERE `name`='用户99999'; -- 执行耗时 : 0.283 sec
查询了995053行
给name创建完索引之后
SELECT * FROM app_user WHERE `name`='用户999'; -- 0sec
只查了一行
索引在小数据的情况下用处不大,,在用户量大的时候区别非常明显。
7.3索引原则
- 索引不是越多越好
- 不要对进程变动数据加索引
- 小数据量的表不需要加索引
- 索引一般加在常用来查询的字段上
索引的数据结构
hash类型的索引
默认是Btree: innodb的默认数据结构
运维级别mysql学习
8、权限管理
8.1、用户管理
sqlyog可视化管理
sql命令操作
用户表:mysql.user
本质:对这张表进行增删改查
8.2mysql备份
为什么要备份?
- 保证重要的数据不丢失
- 数据转移
mysql数据备份的方式
- 直接拷贝物理文件
- 在sqlyog这种可视化工具中手动导出
- 使用命令行导出导入 mysqldump 命令行使用
- mysqldump -hlocalhost -uroot -p123456 school student>D:/a.sql
- mysqldump -h主机 -u 用户名 -p 密码 数据库 表1 表2 表3…>物理磁盘位置,文件名
- source 登陆的情况下,切换到指定数据库 source 备份文件
把数据库给朋友,sql文件给朋友即可。
9、规范数据库设计
9.1为什么需要设计
当数据库比较复杂的时候,我们就需要设计了
糟糕的数据库设计:
- 数据冗余,浪费空间
- 数据库插入和删除都会麻烦、异常(屏蔽使用物理外键)
- 程序的性能差
良好的数据库设计:
- 节省内存空间
- 保证数据库的完整性
- 方便我们开发系统
软件开发中,关于数据库的设计
- 分析需求:分析业务和需求处理的数据库的需求
- 概要设计:设计关系图 E-R图
设计数据库的步骤(个人博客)
- 收集信息,分析需求
- 用户表(用户登录注销,用户的个人信息,写博客、创建分类)
- 分类表(文章分类,谁创建的)
- 文章表(文章的信息)
- 评论表 (评论的信息)
- 友链表(友链信息)
- 自定义表(系统信息,某个关键的字,或者一些主字段) key:value
- 标识实体(把需求落地到每个字段)
9.2三大范式(了解即可)
为什么需要数据库规范化?
- 信息重复
- 更新异常
- 插入异常
- 无法正常显示信息
- 删除异常
- 丢失有效的异常
三大范式
-
第一范式:要求一张表中的数据每一列都是不可分割的原子项数据
-
第二范式(满足第一范式):消除部分依赖,要求一张表中的每一列都完全依赖于主键(针对于组合主键),也就是不会出现某一列只和部分主键相关。
-
第三范式(满足第二、三范式):消除传递依赖,要求一张表中的每一列都和主键是直接依赖的,不是间接依赖。
规范数据库设计
规范性和性能的问题
关联查询的表不能超过三张表- 考虑商业化的需求和目标(成本,用户体验)数据库的性能更加重要
- 在考虑性能问题的时候,需要适当考虑一下规范性。
- 故意给某些表增加一些冗余的字段(从多表查询编程单表查询)
- 估计增加一些计算列(从大数据量变为小数据量的查询:索引)
10.JDBC(重点)
10.1数据库驱动
驱动:声卡、显卡、数据库
我们的程序会通过数据库驱动和数据库打交道!
10.2JDBC
对数据库的统一规范JDBC(java操作数据库)
10.3第一个JDBC程序
1、创建一个普通项目
2、导入数据库驱动
3、编写测试代码
package lesson01;
import java.sql.*;
//第一个JDBC程序
import java.sql.*;
public class JdbcFirstDemo {
public static void main(String[] args) {
try {
//1.注册驱动 固定写法,加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.创建连接
// useUnicode=true
// characterEncoding=utf8
// useSSL=true
String url = "jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&useSSL=false";
String username = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url,username , password);
//3.连接成功,返回数据库对象
String sql = "select * from users";
Statement statement = connection.createStatement();
//4.执行sql
ResultSet resultSet = statement.executeQuery(sql);
//5.遍历结果集
while (resultSet.next()){
System.out.println("id:"+resultSet.getString("id")+" name:"+
resultSet.getString("name")
+" password: "+resultSet.getString("password"));
}
resultSet.close();
statement.cancel();
connection.close();
} catch (Exception e) {
}
}
}
DriverManager
//1.注册驱动 固定写法,加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//Connection 代表数据库
//数据库设置自动提交
URL
String url = "jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8";
String url = "jdbc:mysql://localhost:3306/jdbcstudy";
jdbc:mysql://主机名:端口号/数据库名?参数1&参数2&参数3
//oracle --1521
jdbc:oracle:thin:@localhost:1521:sid
Connection
connection.commit(); //设置提交事务
connection.isReadOnly();//是否只读
connection.setAutoCommit(true);//设置事务自动提交
Statement
statement.executeQuery(sql);//执行查询,返回一个结果集
statement.execute();//执行任何SQL
statement.executeUpdate();//执行更新操作:插入、修改、删除,返回受影响的行数
ResultSet查询的结果集:封装了所有的查询结果
--- 在不知道类型的情况下使用getObject类型
resultSet.getObject();
-- 在知道类型的情况下使用对应类型
resultSet.getString();
resultSet.getBigDecimal();
resultSet.getFloat();
resultSet.getDate();
resultSet.getDouble();
resultSet.getInt();
resultSet.getLong();
...
遍历,指针
resultSet.next();//移动到下一个
resultSet.beforeFirst();//移动到第一个
resultSet.afterLast();//移动到最后面
resultSet.previous();//移动到前一行
resultSet.absolute(row);//移动到指定行
释放资源
resultSet.close();
statement.cancel();
connection.close();
10.4、statement
jdbc中的statement 用于向数据库发送SQL语句,想要完成对数据库的增、删、改、查,只需要通过这个对象向数据库发送增删改查语句即可
Statement 对象的 executeUpdate方法,用于向数据库 发送增、删、改的SQL语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致数据库几行数据发生了变化)
Statement. executeQuery()方法用于向数据库发送 查询语句,executeQuery()方法返回代表查询结果的ResultSet对象。
insert
Statement statement = connection.createStatement();
String sql = "insert into user(...) values(...)"
int num = statement.executeUpdate(sql);
if(num > 0){
System.out.println("插入成功");
}
CRUD操作–delete
Statement statement = connection.createStatement();
String sql = "delete from user where id = 1"
int num = statement.executeUpdate(sql);
if(num > 0){
System.out.println("删除成功");
}
CRUD操作–update
Statement statement = connection.createStatement();
String sql = "update user set name='' where id = 1"
int num = statement.executeUpdate(sql);
if(num > 0){
System.out.println("修改成功");
}
CRUD操作–select
Statement statement = connection.createStatement();
String sql = "select * from user";
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
//根据获取列的数据类型,分别调用rs的相应方法映射到java对象中
}
10.5sql注入问题
sql注入问题
sql存在漏洞
sql 存在漏洞,会被攻击,导致数据泄漏。SQL会被拼接
preparedStatement 可以防止SQL 注入,效率更好!
10.5PreparedStatement对象
可以防止sql注入,并且效率更高。
使用?占位符
st.setString(4,“1”);
填充的时候用set来填充
10.6 JDBC事务
例子:
package le4;
import le2.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction {
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("Success");
} catch (SQLException throwables) {
//如果失败则回滚
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
10.7数据库连接池
数据库连接——执行完毕——释放十分消耗资源
池化技术:准备一些预先的资源,过来就连接,使用预先准备好的服务。
省去connection.