数据库增强

时间:2022-06-20 01:36:03

01.什么是数据库
1) 思考: 你知道的存储数据的方式有几种?
变量, 常量, 数组, 集合:
可以对数据进行临时性存储, 程序执行结束后数据就丢失了.
IO流 :
可以对数据进行永久性存储, 但是不方便用户进行精细化管理.
数据库:
就是存储数据的仓库, 其本质是一个文件系统, 可以有规律的对数据进行存储, 方便用户进行增删改查.
//增删改查: CURD(create, update,read,delete)
//记忆: 数据库才是实际开发中我们真正存储数据的地方.

2) 我们常说的数据库其实指的是数据库管理系统(DBMS), 那数据库管理系统和数据库之间有什么关系?
数据库管理系统: DataBase Management System
类似于: Idea, Eclipse, MyEclipse
数据库:
类似于: Idea中的项目

数据表:
类似于: Java(项目)中的类

数据表中的数据: //BeanHandler
类似于: Java中的实体对象.

3) 常见的数据库管理系统(DBMS)有哪些? //常见的数据库有哪些?
MySQL, Oracle, SQLServer, DB2, SyBase, SQLite.


02. 我们常用的这些数据库管理系统都是: 关系型数据库, 那么什么是关系型数据库呢?
关系型数据库:
其实描述的就是实体与实体之间的关系.
//记忆: 关系型数据库就是在描述数据表与数据表之间的关系(一对多, 多对多, 一对一).

ER模型图(Entity Relational Model)
实体: 矩形
属性: 椭圆形
关系: 菱形

非关系型数据库: //压根就没有数据表的概念, Key-Value型数据库.
Redis, HBase

03. MySQL的基础操作
1) MySQL的登陆和退出
登陆:
方式一:
window徽标键 字母r --> cmd --> mysql -u root -p --> 回车 --> 录入密码 --> 回车

方式二:
window徽标键 字母r --> cmd --> mysql -u用户名 -p密码 --> 回车

退出:
方式一:
exit --> 回车 //正常退出
方式二:
ctrl c //强制退出.

2) MySQL的基础函数(查看版本, 查看时间等)
select version(); //查看当前MySQL的版本
select current_Date(); //获取日期(年月日)
select curDate(); //获取日期(年月日)
select current_Time(); //获取时间(时分秒)
select curTime(); //获取时间(时分秒)
/*
补充演示:
select sin(pi()/3); //获取正弦值
select pi(); //获取圆周率pi的值
select (4 1)*5; //获取组合运算的结果
*/

3) 小细节
A: SQL语句不区分大小写, 只要单词别写错即可.
B: SQL语句以分号结尾, 一个分号就代表是一句SQL的结束.
C: 写到一半, 如果不想执行该SQL语句了, 在SQL后面加上c 然后回车即可.


04. SQL语句操作数据库及数据表
1) 概述:
SQL: Structured Query Language, 结构化查询语言.
//人和数据库之间进行交互的语言.

2) SQL语句操作数据库(CURD)
增:
创建数据库: create database 数据库名;
删:
删除数据库: drop database 数据库名;
改:
修改数据库的码表:
alter database 数据库名 charset 指定的字符集;
alter database 数据库名 character set 指定的字符集;
查:
查询所有的数据库
show databases;
查询指定数据库(字符集)
show create database 数据库名;
使用指定的数据库(切换库):
use 数据库名;

3) SQL语句操作数据表
增:
创建数据表: //掌握
create table 数据表名(
列名1 数据类型 [约束],
列名2 数据类型 [约束],
列名3 数据类型 [约束]

);

约束
作用: 用来保证数据的完整性和安全性.
分类:
单表约束:
主键约束: primary key //auto_increment(自动增长)
唯一约束: unique
非空约束: not null
多表约束:
外键约束: foreign key


删:
删除数据表: drop table 数据表名;
改: //了解, 因为修改表结构的动作很危险, 所以自己新建一个库, 测试几次即可.
给表增加一列字段
alter table 表名 add 列名 数据类型 约束;
修改某列字段的约束和类型
alter table 表名 modify 列名 数据类型 约束;
修改某列字段的名字,约束,类型
alter table 表名 change 旧列名 新列名 数据类型 约束;
删除指定的列
alter table 表名 drop 列名;
修改表名
rename table 旧表名 to 新表名;
修改表的码表
alter table 表名 character set 指定的码表;
alter table 表名 charset 指定的码表;

查:
查询所有的数据表
show tables;

查询指定数据表(表结构)
desc 数据表名;

05. SQL语句操作表数据之添加
1) 通过insert语句实现.
A: 创建表.
create table users(
uid int primary key auto_increment,
uname varchar(20),
age int
);
B: 通过SQL语句插入数据.
insert into users values(null,‘王丽坤‘, 23), (null,‘刘亦菲‘,31);

2) 通过加载文件的方式将数据导入到表中.
A: 创建表
CREATE TABLE pet ( #宠物表
name VARCHAR(20),
owner VARCHAR(20),
species VARCHAR(20),
sex CHAR(1),
birth DATE,
death DATE
);

B: 从文件中加载数据.
a. 在本地创建一个pet.txt文件, 名称可以自定义. //注:每个字段中用tab键隔开,字段没有值得记录用N代替
b. 执行加载文件的SQL将其导入表中:
格式:
load data local infile ‘本地路径‘ into table 表名;
范例:
load data local infile ‘/root/pet.txt‘ into table pet;

c. 检验是否已经导入成功:
select * from 表名 ;
d. 注意: //以下为Linux指令.
put -a 文件路径 //将指定文件上传到服务器.
示例: put -a D:compilepet.txt
rm -rf 文件名 //移除指定的文件.
示例: rm -rf test01.sql

06. SQL语句操作表数据之删改查
1) 删除表数据
delete from 数据表名 where 条件; //删除表数据, 不会重置主键ID.
truncate table 数据表名; //删除表数据, 会重置主键ID.

2) 修改表数据
update 数据表名 set 列名1=值,列名2=值,列名3=值 where 条件;

3) 查询表数据
A. 最基本的查询:
select * from 数据表名; //全列名
select 列名1,列名2,列名3 from 数据表名; //指定列名

B. 带别名的查询:
关键字 as

C. 带条件的查询:
a. 条件运算符
>,<, >=, <=, =, !=(<>)
b. 区间(范围)运算符
between 值1 and 值2;
c. 逻辑运算符
and or not
d. 固定值的查询
in (值1,值2,值3)
e. 模糊查询
like 条件.
//一般会结合占位符使用.
//_占一个位置 %占多个位置

D. 如果表中有重复数据, 可以将其去重: distinct
select distinct 字段名称1,字段名称2... from 表名;

E. 排序操作: order by
格式:
SELECT * 字段列表 FROM 表名 ORDER BY 排序字段1 [排序方式],排序字段2 [排序方式];

排序方式:
desc(降序) 和 asc(升序), 默认为升序排序

如果是多个字段排序, 会先按照第一个字段进行排序,如果第一个字段有相同的, 然后在按照第二个字段排序

F. 日期计算
select year(‘1988-01-01‘); //获取年份, 即: 打印结果是为 1988


G. is null和 is not null值
格式:
字段 is null //筛选这个字段为null的数据
字段 is not null //筛选这个字段不为null的数据

07. 小案例
1) 创建表, 添加数据.
CREATE TABLE shop (
article INT(4) UNSIGNED ZEROFILL DEFAULT ‘0000‘ NOT NULL,
dealer CHAR(20) DEFAULT ‘‘ NOT NULL,
price DOUBLE(16,2) DEFAULT ‘0.00‘ NOT NULL,
PRIMARY KEY(article, dealer)
);


INSERT INTO shop VALUES
(1,‘A‘,3.45),(1,‘B‘,3.99),(2,‘A‘,10.99),(3,‘B‘,1.45),
(3,‘C‘,1.69),(3,‘D‘,1.25),(4,‘D‘,19.95);

2) 完成如下的需求:
A. 检索表中的全部数据.
select * from shop;

B. 求某一列的最大值或者最小值.
select max(price) from shop;

C. 求价格最高的那条数据.
select * from shop where price = (select max(price) from shop);

select * from shop order by price desc limit 0,1;

D. 求出每一列的最大值,并且根据某一个字段进行分组.
SELECT article, MAX(price) AS price FROM shop GROUP BY article;

E. 写到你的本上, 哪怕是背也要背下来.
一个完整的SQL语句的模块:
select [distinct] 列名1, 列名2 as ‘别名‘,列名3... from 表名 where 分组前的条件筛选
group by 要分组的列 having 分组后的条件筛选 order by 要排序的列 [asc/desc] limit 起始索引, 结束索引;


08. SQL中的聚合函数
count(); //一般用于获取数据表的行数.
max(); //获取某一列的最大值.
min(); //获取每一列的最小值.
avg(); //获取某一列的平均值.
sum(): //获取某一列的和.


09. SQL语句的分类 //Structured Query Language, 结构化查询语言.
DDL: 数据定义语言. 主要指的是操作数据库, 操作数据表, 增加列.
//create, drop, alter
DML: 数据操作语言. 主要指的是操作数据, 增删改. //update, insert, delete
//SQL语句中,把对数据的增删改操作合称为: 更新语句.
//DML语句可以和 事务 相结合使用.
事务:
张三10000, 李四10000

开启事务
张三 - 1000
sop(1/0);
李四 1000
提交事务: commit
事务回滚: rollback

DCL: 数据控制语言. 主要指的是 创建用户, 设置权限, 设置安全级别. //create, grant
DQL: 数据查询语言. 主要指的是操作数据: 查询.
//select, from, where

10. 数据库的备份和还原
1) 备份命令
格式:
mysqldump -u 用户名 -p 数据库名 > 磁盘SQL文件路径
//由于mysqldump命令不是sql命令,需要在dos窗口下使用。
示例:
mysqldump -uroot -p123456 test01 >/root/test01.sql
//其中: test01是数据库的名字

2) 恢复命令
//注意: 恢复数据库,需要手动的先创建数据库:

格式:
create database test01; //创建数据库
mysql -u 用户名 -p 数据库名 < 磁盘SQL文件路径

示例:
mysql -uroot -p123456 test01 < /root/test01.sql

3) 注意:
在备份数据的时候,数据库不会被删除。可以手动删除数据库。同时在恢复数据的时候,
不会自动的给我们创建数据库,仅仅只会恢复数据库中的表和表中的数据。

4) 备份数据表. //备份数据表的时候, 只会备份结构(字段)和数据, 不会备份主键(约束).
备份表不存在:
create table 数据表名 select * from 要备份的数据表名;

备份表存在:
insert into 数据表名 select * from 要备份的数据表名;


11. 多表查询
1) 准备数据.
create table A(
A_ID int primary key auto_increment,
A_NAME varchar(20) not null
);
insert into A values(1,‘apple‘);
insert into A values(2,‘orange‘);
insert into A values(3,‘banana‘);

create table B(
A_ID int primary key auto_increment,
B_PRICE double
);
insert into B values(1,2.30);
insert into B values(2,3.50);
insert into B values(4,null);

交叉查询: //理解, 没有什么特殊意义.
格式:
select * from 表A,表B; //查询结果是两张表的: 笛卡尔积.
//笛卡尔积指的是两张表(总条数)的乘积: 表A的总条数 * 表B的总条数

连接查询:
内连接查询: inner join
显示内连接:
select * from 表A inner join 表B on 条件;
//select * from 表A join 表B on 条件;

隐式内连接:
select * from 表A,表B where 条件;

外连接查询: outer join
左外连接查询:
select * from 表A left outer join 表B on 条件;
//select * from 表A left join 表B on 条件;

右外连接查询:
select * from 表A right outer join 表B on 条件;
//select * from 表A right join 表B on 条件;

子查询:
概述:
一个SQL语句的条件需要依赖另一个SQL语句的查询结果.

常用关键词的用法:
in: 只要满足其中一个就行.
//回忆:age=23 or age=24? 等价于 age in (23,24)
//in 表示条件应该是在多个列值中。
//in:使用在where后面,经常表示是一个列表中的数据,只要被查询的数据在这个列表中存在即可。

exists: //表示存在,当子查询的结果存在,就会显示主查询中的所有数据。
select * from A where exists(select A_ID from B);

union和union all的使用法 //要求拼接双方的表结构一致.
UNION语句:
用于将不同表中相同列中查询的数据展示出来;(不包括重复数据)
//select * from A union select * from B;

UNION ALL 语句:
用于将不同表中相同列中查询的数据展示出来;(包括重复数据)

case when语句:
格式:
CASE sex
WHEN ‘1‘ THEN ‘男‘
WHEN ‘2‘ THEN ‘女‘
ELSE ‘其他‘ END

12. mysql数据类型
1) 概述
MySQL中定义数据字段的类型对你数据库的优化是非常重要的。
MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。

2) 常用数据类型:
数值类型 //MySQL支持所有标准SQL数值数据类型。
tinyint, int, double //Decimal(D,M); D:表示总长度, M: 表示小数位数.

日期和时间类型:
Date: 年月日
Time: 时分秒
DateTime: 可以自定义时间.
StampDate: 时间戳, 采用当前系统的默认时间.

字符串类型
CHAR: 0-255字节, 定长字符串, 未存满则后边用空格补齐.
VARCHAR: 0-65535字节, 变长字符串, 后边不会用空格补齐.
BLOB: 以二进制形式存储, 例如: 图片, 音频, 视频等.
TEXT(CLOB): 以文本文件形式存储.

13. SQL语句之分组, 模糊查询, 空值处理.
1) 分组
//GROUP BY 语句根据一个或多个列对结果集进行分组。

2) 模糊查询
字段 like 值; //注意: like一般结合%(占n个位置),_(占一个位置)使用.

3) 空值处理
is null //当列的值是 NULL,此运算符返回 true。
is not null //当列的值不为 NULL, 运算符返回 true。
<=> //null和null比较返回1(true), 其他返回0(false)

14. MySQL 元数据
1) 你可能想知道MySQL以下三种信息:
查询结果信息:
SELECT, UPDATE 或 DELETE语句影响的记录数。
数据库和数据表的信息:
包含了数据库及数据表的结构信息。
MySQL服务器信息:
包含了数据库服务器的当前状态,版本号等。
//在MySQL的命令提示符中,我们可以很容易的获取以上服务器信息。

2) 具体的元数据命令
SELECT VERSION() //服务器版本信息
SELECT DATABASE() //当前数据库名(或者返回空)
SELECT USER() //当前用户名
SHOW STATUS //服务器状态
SHOW VARIABLES //服务器配置变量


15. MySQL的常用函数
1) 字符串函数 //参考Java中的String#一些方法
CONCAT(); //字符串 s1,s2 等多个字符串合并为一个字符串
LCASE(); //将字符串 s 的所有字母变成小写字母
LOWER(); //将字符串 s 的所有字母变成小写字母
UCASE(); //将字符串 s 的所有字母变成大写字母
UPPER(); //将字符串 s 的所有字母变成大写字母
REVERSE(); //反转
SUBSTRING(); //截取 例如: select substring(‘hello黑马程序员Java‘, 6, 5);

2) 数字函数 //参考Java中的Math#一些方法
ABS(); //求绝对值
CEIL(); //求天花板数
FLOOR(); //求地板数
PI(); //求圆周率
RAND(); //获取0~1之间的随机数, 例如: select floor(rand()*100) 1; 获取1~100之间的随机数.
ROUND(); //四舍五入

count(); //聚合函数
max();
min();
avg();
sum();

3) 日期函数
NOW(); //获取当前时间
YEAR(); //获取年份
MONTH(); //获取月份
DAY(); //获取天

4) 高级函数
VERSION();
USER();
DATABASE();

16. MySQL的索引
概述:
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

分类:
索引分单列索引和组合索引。
单列索引:
即一个索引只包含单个列,一个表可以有多个单列索引.
组合索引:
即一个索引包含多个列。

注意:
1) 创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
2) 实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
3) 上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,
同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
4) 建立索引会占用磁盘空间的索引文件。
5) 我们以前用的"主键约束", "唯一约束"都属于: 唯一索引.

具体用法:
1) 显示索引信息
SHOW INDEX FROM 数据表名; G //加入"g", 会让格式看起来更规整.
2) 创建索引.
create index 索引名 on 数据表名(字段名(长度));
示例:
create index id_Index on A(A_ID);

3) 删除索引.
alter table 数据表名 drop index 索引名;

17. 事务的概述
概述:
事务指的是逻辑上的一组操作, 组成该逻辑操作的逻辑单元, 要么全部成功, 要么全部失败.

/*
记忆:
MySQL默认开启了事务的自动提交功能, 每一个SQL语句都是一个事务.
Oracle默认没有开启事务的自动提交功能, 需要手动提交.

事务可以和 DML(用来执行更新语句的, 增删改)语句相结合使用.


MySQL数据库的默认隔离级别是: repeatable read
Oracle数据库的默认隔离级别是: read committed
*/


事务的特点: //ACID
1) 原子性.
强调事务的多个操作不可分割.
2) 一致性.
强调事务执行的前后, 数据完整性保持一致.
3) 隔离性 //重点.
强调事务执行过程中, 不应该受到其他事务的干扰.
4) 持久性
强调事务一旦结束, 数据就持久到数据库中.

如果不考虑隔离性, 有可能出现以下问题:
关于读的问题:
脏读: //读-未提交
指的是: 一个事务读取到了另一个事务还没有提交的数据.

不可重复读: //读-已提交
指的是: 一个事务读取到了另一个事务提交过的: 修改的数据.
导致多次查询结果不一致.


虚读: //有些书中可能会把它写成"幻读", 这个了解就行.
指的是: 一个事务读取到了另一个事务提交过的: 添加的数据.
导致多次查询结果不一致.


关于写的问题: //暂时了解.
丢失更新.


其实所谓的"考虑隔离性", 其实就是设置"隔离级别":
隔离级别权限从小到大分别是:
read uncommitted < read committed < repeatable read < serializable

安全性从小到大分别是:
read uncommitted < read committed < repeatable read < serializable

效率从高到低分别是:
read uncommitted > read committed > repeatable read > serializable

read uncommitted: 有可能引发脏读, 不可重复读, 虚读.
read committed: 能规避脏读, 但是有可能发生不可重复读, 虚读.
repeatable read: 能规避脏读, 不可重复读, 但是有可能发生虚读.
serializable: 串行化的, 能规避这三种.

18. 事务的隔离性演示 //模拟转账的案例
涉及到的SQL语句:
//佳乐 给 凤姐 转 1000块钱.
开启事务;
start transaction;
SQL语句1;
//update account set money = money - 1000 where aid = 1;
SQL语句2;
//update account set money = money 1000 where aid = 2;
提交事务;
commit;
事务回滚; //事务回滚会把数据还原该该事务执行之前的状态.
rollback;



show variables like ‘%commit%‘; //查看MySQL是否开启了"事务的自动提交"功能.
select @@tx_isolation; //查看当前事务的隔离级别.
set session transaction isolation level 隔离级别; //设置当前事务的隔离级别.

演示"脏读":
1. 开启两个cmd窗口A, B.
2. 查看当前的事务的隔离级别:
select @@tx_isolation
//默认为: repeatable read
3. 将A窗口的隔离级别修改为: read uncommitted;
set session transaction isolation level read uncommitted;
4. 再次查看下两个窗口的的隔离级别:
select @@tx_isolation;
5. 在A, B两个窗口中分别开启事务:
6. 在B窗口中完成转账.
//注意: 先不要提交事务.
7. 在A窗口中进行查询.
//发现转账已经成功, 说明脏读已经发生了.
//脏读: 一个事物读取到另一个事务未提交的数据.

演示"不可重复读"的产生:
1. 开启两个cmd窗口A, B.
2. 查看当前的事务的隔离级别:
select @@tx_isolation
//默认为: repeatable read
3. 将A窗口的隔离级别修改为: read committed;
set session transaction isolation level read committed;
4. 再次查看下两个窗口的的隔离级别:
select @@tx_isolation;
5. 在A, B两个窗口中分别开启事务:
6. 在B窗口中完成转账.
//注意: 先不要提交事务.
7. 在A窗口中进行查询.
//发现A窗口中的数据没有变化, 说明脏读没有发生.
//脏读: 一个事物读取到另一个事务未提交的数据.
8. 在B窗口中提交事务.
//发现A窗口中的数据已经变化了, 说明"不可重复读"已经产生了,
//不可重复读: 指的是一个事务读到了另一个事务已经提交的 update的数据,
//导致多次查询结果不一致.


19. 数据库并发的控制
1) 并发调度的可串行化
可串行化准则:
多个事务的并发执行时正确的,当且仅当其结果按某一次序串行执行它们时的结果相同,这种调度策略称为可串行化调度。
可串行化是并发事务正确性的准则,一个给定的并发调度,当且仅当它是可串行化的,才认为是正确的。

2) *
*是实现并发控制的非常重要的技术。*是指某事务在对某数据对象进行操作以前,先请求系统对其加锁,
成功加锁之后该事务就对该数据对象有了控制权,只有该事务对其进行解锁之后,其他的事务才能更新它.

3) 锁的分类: //DBMS有两种锁:
A: 排它锁(也称作X锁): 可读可写
如果事务T在对某个数据对象实施了X锁,那么其他的事务必须要等到T事务接触对该数据对象的X锁之后,才能对这个数据进行加锁。

B: 共享锁(也称作S锁):只能进行读取工作
如果事务T在对某个数据对象实施了S锁,那么其他的事务也能对该数据对象实施S锁,但是对这个数据对象施加的所有S锁都释放之前
不允许任何事务对该数据对象实施X锁。

4) *技术之活锁和死锁.
问题描述:
*技术可以避免一些并发操作引起的不一致错误,但也会产生其他的一些问题,活锁和死锁。

活锁:
如果某个事务处在永远等待的状态,得不到*的机会,这种现象为活锁,避免这种锁最好的方法就是采用先来先服务的策略。

死锁:
两个或两个以上的事务都处于等待状态每个事务都在等待对方事务接触*,它才能继续执行下去,
这样任何事务都处于等待状态而无法继续执行的现象称为死锁


解决方案: //解决死锁问题方法有两类:
A、 死锁的预防
B、 死锁的诊断与预防
//大白话: 尽量别写这样的代码, 如果出现问题了, 只能手动修改源代码.





Java中String类中的常用方法:
判断功能: //首尾中空加判断
startsWith();
endsWith();
contains();
isEmpty();
equals();
equalsIgnoreCase();

获取功能: //截长取位取元素
substring()
length()
indexOf();
lastIndexOf();
charAt();

转换功能: //大小拼串转数组
toUpperCase();
toLowerCase();
concat();
toCharArray();
getBytes();

其他功能: //除空切换字典排
trim();
split();
replace();
compareTo();









2019-10-27