曾经的Mysql学习笔记

文件保存数据缺点:

​ 文件的安全性问题

​ 文件不利于数据查询和管理

​ 文件不利于存储海量数据

​ 文件在程序中控制不方便

连接服务器

mysql -h 127.0.0.1(默认本地连接) -P 3306(端口号) -u root(用户名)-p xxx(密码,明文,不推荐)

注意:连接前需要打开mysql服务 (运行窗口:services.msc 打开服务)或者

​ 命令行 net start/stop MySQL57(你的服务名)开启/关闭服务

MYSQL架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlkxt8TN-1585360158449)(F:\courseware_note\MySQL课件\mysql_framework.png)]

(1)MySQL向外提供的交互接口(Connectors)

​ Connectors组件,是MySQL向外提供的交互组件,如java,.net,php等语言可以通过该组件来操作SQL语 句,实现与SQL的交互。

(2)管理服务组件和工具组件(Management Service & Utilities)

​ 提供对MySQL的集成管理,如备份(Backup),恢复(Recovery),安全管理(Security)等

(3)连接池组件(Connection Pool)

​ 负责监听对客户端向MySQL Server端的各种请求,接收请求,转发请求到目标模块。每个成功连接MySQL Server的客户请求都会被创建或分配一个线程,该线程负责客户端与MySQL Server端的通信,接收客户端发送的命令,传递服务端的结果信息等。

(4)SQL接口组件(SQL Interface)

​ 接收用户SQL命令,如DML,DDL和存储过程等,并将最终结果返回给用户。

(5)查询分析器组件(Parser)

​ 首先分析SQL命令语法的合法性,并尝试将SQL命令分解成数据结构,若分解失败,则提示SQL语句不合理。

(6)优化器组件(Optimizer)

对SQL命令按照标准流程进行优化分析。

(7)缓存主件(Caches & Buffers)

缓存和缓冲组件

(8)插件式存储引擎(Pluggable Storage Engines)

​ MySQL存储引擎在MySQL中扮演重要角色,其作比较重要作用,大致归结为如下两方面:

​ 作用一:管理表创建,数据检索,索引创建等

​ 作用二:满足自定义存储引擎开发。

(9)物理文件(File System)

实际存储MySQL 数据库文件和一些日志文件等的系统,如Linux,Unix,Windows等。

存储引擎的查看及对比

查看存储引擎

show engines;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rpFcgYse-1585360158451)(F:\courseware_note\MySQL课件\showengines.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJ07tGVq-1585360158452)(F:\courseware_note\MySQL课件\enginnes.png)]

不同的存储引擎,创建表的文件不一样。

MyISAM 在数据目中有三个不同的文件,分别是

.frm:表结构

.MYD:表数据

.MYI:表索引

innodb 在数据目录中有两个不同的文件,分别是

.frm:表结构

.ibd:表数据,表索引

总结:

常用的三种引擎对比(innodb,MyISAM,memory)

//TODO

SQL分类

DDL数据定义语言

用来维护存储数据的结构

代表指令: create, drop, alter

DML数据操纵语言

用来对数据进行操作

代表指令: insert,delete,update

DML中又单独分了一个DQL数据查询语言

代表指令: select

DCL数据控制语言

主要负责权限管理和事务

代表指令: grant,revoke,commit

库的操作

创建库
CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...]
 
create_specification:   
[DEFAULT] CHARACTER SET charset_name    //指定数据库采用的字符集
[DEFAULT] COLLATE collation_name        //指定数据库字符集的校验规则
查看系统默认字符集以及校验规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SxuVU3kZ-1585360158452)(F:\courseware_note\MySQL课件\charset_collation.png)]

查看数据库支持的字符集/校验规则
show charset;
show collation;

注意:

​ utf8_ general_ ci [不区分大小写]

​ utf8_ bin [区分大小写]

操作库
显示创建语句
mysql> show create database mytest;
+----------+----------------------------------------------------------------+ 
| Database | Create Database                                                | 
+----------+----------------------------------------------------------------+ 
| mysql    | CREATE DATABASE `mytest` /*!40100 DEFAULT CHARACTER SET utf8 */ | 
+----------+----------------------------------------------------------------+

说明:
MySQL 建议我们关键字使用大写,但是不是必须的。

​ 数据库名字的反引号``, 是为了防止使用的数据库名刚好是关键字

​ /*!40100 default… */ 这个不是注释,表示当前mysql版本大于4.01版本,就执行这句话

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2SDD0bx-1585360158454)(F:\courseware_note\MySQL课件\without_keyword.png)]

修改数据库

对数据库的修改主要指的是修改数据库的字符集,校验规则

create—>alter 语法相同

删除数据库
DROP DATABASE [IF EXISTS] db_ name;

执行删除之后的结果:

数据库内部看不到对应的数据库

对应的数据库文件夹被删除,级联删除,里面的数据表全部被删

不要随意删除数据库!!!!

备份和恢复

备份操作(退出连接) 不用连接数据库也可执行

备份库

mysqldump -P3306 -u root -p 密码 -B 数据库名1 数据库名2 ... > 数据库备份存储的文件路径.sql

备份表

mysqldump -P3306 -u root -p 密码 -B 数据库名 表1 表2 ... > 数据库备份存储的文件路径.sql

恢复

source 备份的路径.sql;

注意:

​ 如果备份一个数据库时,没有带上-B参数, 在恢复数据库时,需要先创建空数据库,然后使用数据库,再使

用source来还原。

查看连接情况
show processlist

​ 告诉我们当前有哪些用户连接到我们的MySQL,如果查出某个用户不是你正常登陆的,很有可能你的数据库被 人入侵了。如果发现自己数据库比较慢时,可以用这个指令来查看数据库连接情况。

表的操作

创建表
CREATE TABLE table_name (    
    field1 datatype [commit],    
    field2 datatype [commit],    
    field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;
    //commit 注释 对字段的描述
查看表结构
desc 表名;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VSTR6bi6-1585360158454)(F:\courseware_note\MySQL课件\tablestructure.png)]

修改表

修改表的结构,比如字段名字,字段大小,字段类型,表的字符集类型,表的存储引擎等等。

添加(add)/修改(modify)/删除(drop)字段等等。这时我们就需要修改表。

ALTER TABLE  tablename ADD (column datatype [DEFAULT expression][,column datatype]...);
 
ALTER TABLE  tablename MODIfy (column datatype [DEFAULT expression][,column datatype]...);
 
ALTER TABLE  tablename DROP (column);

定位添加一个字段(对原表数据没有影响) add

 alter table 表名 add field datatype [comment 'xxx' after field(已存在字段)];

修改一个字段类型或字段类型长度 modify

alter table 表名 modify field datatype 约束条件;

删除一个字段 drop(删除字段会将对应列的数据都删除)

alter table 表名 drop field;

修改表名 rename (to) to可以省略

 alter table 表名 rename (to) 新名称;

修改字段名(列名) change eg. 将name 改为 xingming。

alter table 表名 change name xingming varchar(60); --新字段需要完整定义
删除表
DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ...

数据类型

数据类型分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bi2y0FW3-1585360158455)(F:\courseware_note\MySQL课件\datatype.png)]

数值类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bU0KCuCO-1585360158456)(F:\courseware_note\MySQL课件\int.png)]

默认有符号

尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下,直接将int类型提升为bigint类型。

bit类型
bit[(M)] : 位字段类型。M表示每个值的位数,1到64。如果M被忽略,默认为1。

bit字段在显示时,是按照ASCII码对应的值显示。(若插入65,则显示A)

值只存放0或1,这时可以定义bit(1)。这样可以节省空间。

float类型
float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节

float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。

decimal
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数 m省略默认为10 d省略默认为0

和float的区别:

​ decimal的精度更准确,比float精度更高(float表示的精度大约是七位)

​ decimal最大整数位m为65,支持小数最大尾数d是30

如果需要更高的精度,使用decimal

字符串类型
char
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
varchar
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节

char(2)/varchar(2) 可存储 ab 或者 工大 按个数算。

关于varchar(len),len到底是多大,这个len值,和表的编码密切相关:
varchar长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是 65532。

​ 当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844[因为utf中,一个字符占用3个字 节]

​ 如果编码是gbk,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节)。

char和varchar的比较

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GQcbEfTI-1585360158456)(F:\courseware_note\MySQL课件\char_varchar.png)]

如何选择?

总结: (char)定长的磁盘空间比较浪费,但是效率高 。如果数据确定长度一样,使用char

​ 例如:身份证号,手机号

​ (varchar)变长的磁盘空间比较节省,但是效率低。如果数据长度有变化,使用varchar

​ 例如:姓名,地址。 但是要保证最长的数据可以存储。

日期和时间类型

常用的日期有如下三个:

​ datetime 时间日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示范围从1000到9999,占用八字节

​ timestamp:时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss格式和datetime完全一致,占用四字节

​ date:日期 ‘yyyy-mm-dd’,占用三字节

timestamp(时间戳)不需要赋值,显示当前时间

enum和set
enum

枚举,单选类型

enum('选项1','选项2','选项3',...);       		最多 65535个选项
set

集合,多选类型

set('选项值1','选项值2','选项值3', ...);		  最多 64个选项

该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;

而且出于效率考虑,这些值实 际存储的是“数字”

枚举enum所对应的数字是1,2,3,4…65535,添加枚举值的时候,也可以添加对应的编号 (但不建议,不利于阅读)

集合set所对应的的数字是1,2,4,8,16,32…最多64个选项

表的约束

约束字段的是字段的数据类型,但单数据类型约束很单一。

为了更好地保证数据的合法性,从业务逻辑角度保证数据的正确性,需要表的约束

空属性

两个值:null(默认值)/ not null

因为空数据没办法参与运算,实际开发中尽可能保证字段不为空

not null 约束的字段 插入数据时不给该字段插值则插入失败

默认值
mysql> create table tt10 (    
    -> name varchar(20) not null,    
    -> age tinyint unsigned default 0,    
    -> sex char(2) default '男'    
    -> ); 

数据在插入的时候不给该字段赋值,就使用默认值

列描述

comment,专门用来表述字段,根据创建语句保存,方便程序员或DBA(数据库管理员)进行了解

注意:

​ comment 注释信息通过 show create 命令查看 , desc 命令查看不到

zerofill(补零)
int(5) unsigned zerofill;

如果宽度小于设定的宽度(int(5),这里设置的是 5),自动填充0。

若插入1,则显示00001,zerofill 只影响显示结果,实际储存的还是1 (可用hex()函数证明)

设置zerofill属性,相当于一种格式化输出而已

主键

primary key

不能重复,不能为空,主键所在列通常是整数类型

一个表只能有一个主键,若多个字段作为主键,可以使用复合主键

mysql> create table tt14( 
    -> id int unsigned, 
    -> course char(10) comment '课程代码', 
    -> score tinyint unsigned default 60 comment '成绩', 
    -> primary key(id, course) -- id和course为复合主键
    -> ); 

追加和删除主键

alter table 表名 add primary key(字段列表);           //	 追加主键
alter table 表名 drop primary key;                   //	删除主键
自增长

​ auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操

作, 得到一个新的不同的值。

​ 自增长的特点:

​ 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)

​ 自增长字段必须是整数

​ 一张表最多只能有一个自增长

通常和主键搭配使用,作为逻辑主键。

唯一键

​ unique:

​ 表中往往有很多字段都需要唯一性,但表中只能有一个主键,唯一键就解决了多个字段需要唯一性约束的问题。

​ 唯一键与主键的区别 :

​ 主键不允许为空

​ 唯一键允许为空,而且允许多个值为空(空字段不做唯一性比较)

外键

​ 定义于主表和从表之间的关系

foreign key (字段名) references 主表(列) ;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ze7ou0n4-1585360158457)(F:\courseware_note\MySQL课件\foreign.png)]

外键约束主要定义在从表上,主表必须有主键约束或者唯一键约束

主键表

create table myclass (        
    id int primary key,        
    name varchar(30) not null comment'班级名'    
);

从表

create table stu (        
    id int primary key,        
    name varchar(30) not null comment '学生名',        
    class_id int,        
    foreign key (class_id) references myclass(id)    
); 

插入

 insert into myclass values(10, 'C++大牛班'),(20, 'java大神班'); 
 insert into stu values(100, '张三', 10),(101, '李四',20); 

外键的列数据必须在主表存在或者为null

 insert into stu values(102, 'wangwu',30);   //没有30班级,所以插入失败
 insert into stu values(102, 'wangwu', null); //表示来了一个学生,还没有分配班级

基本查询(增删改查)

CRUD : Create, Retrieve,Update,Delete

create

INSERT [INTO] table_name [(column [, column] ...)]     
VALUES (value_list) [, (value_list)] ...   
value_list: value, [, value] ...
单行+全列插入

全列插入table_name后的列名可省

INSERT INTO students VALUES (101, 10001, '孙悟空', '11111'); 
多行+指定列插入

value_list 数量必须和指定列数量及顺序一致

INSERT INTO students (id, sn, name) VALUES 
(102, 20001, '曹孟德'), 
(103, 20002, '孙仲谋'); 
插入否则更新

on duplicate

因为主键或唯一键的唯一性约束导致的重复插入失败

INSERT INTO students (id, sn, name) VALUES (100, 10010, '唐大师')    
ON DUPLICATE KEY UPDATE sn = 10010, name = '唐大师'; 
Query OK, 2 rows affected (0.47 sec)
 
-- 0 row affected:      表中有冲突数据,但冲突数据的值和 update 的值相等 
-- 1 row affected:      表中没有冲突数据,数据被插入 
-- 2 row affected:      表中有冲突数据,并且数据已经被更新
替换

replace(推荐使用)

-- 主键 或者 唯一键 没有冲突,则直接插入; 
-- 主键 或者 唯一键 如果冲突,则删除后再插入
 
REPLACE INTO students (sn, name) VALUES (20001, '曹阿瞒'); Query OK, 2 rows affected (0.00 sec)
 
-- 1 row affected:      表中没有冲突数据,数据被插入 
-- 2 row affected:      表中有冲突数据,删除后重新插入

Retrieve

select列
全列查询
select *from table_name;
-- 通常情况下不建议使用 * 进行全列查询 
-- 1. 查询的列越多,意味着需要传输的数据量越大;
-- 2. 可能会影响到索引的使用。(索引待后面课程讲解)
指定列查询

指定列的顺序不需要按定义表的顺序来

查询字段为表达式
SELECT id, name, yingyu + 10 FROM exam_result; 
SELECT id, name, yuwen + shuxue + yingyu FROM exam_result; 
-- 数据库数据不发生改变,只是查询显示改变
查询结果指定别名
SELECT id, name, yuwen + shuxue + yingyu (as) total FROM exam_result;  -- as 不建议省略
结果去重

distinct

SELECT DISTINCT shuxue FROM exam_result;    -- 重复结果不显示
where条件
比较运算符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EPqAhNPZ-1585360158458)(F:\courseware_note\MySQL课件\operator.png)]

where条件使用表达式
-- WHERE 条件中使用表达式 
-- 别名不能用在 WHERE 条件中
 
SELECT name, yuwen + shuxue + yingyu 总分 FROM exam_result     
WHERE yuwen + shuxue + yingyu < 200;
Null的查询

 SELECT name, qq FROM students WHERE qq IS NOT NULL; 
 +-----------+-------+ 
 | name      | qq    | 
 +-----------+-------+ 
 | 孙悟空     | 11111 | 
 +-----------+-------+ 
 1 row in set (0.00 sec)
 
-- NULL 和 NULL 的比较,= 和 <=> 的区别
 
SELECT NULL = NULL, NULL = 1, NULL = 0; 
+-------------+----------+----------+ 
| NULL = NULL | NULL = 1 | NULL = 0 | 
+-------------+----------+----------+ 
|        NULL |     NULL |     NULL | 
+-------------+----------+----------+ 
1 row in set (0.00 sec)
 
SELECT NULL <=> NULL, NULL <=> 1, NULL <=> 0; 
+---------------+------------+------------+ 
| NULL <=> NULL | NULL <=> 1 | NULL <=> 0 | 
+---------------+------------+------------+ 
|             1 |          0 |          0 | 
+---------------+------------+------------+ 
1 row in set (0.00 sec)

结果排序

order by

– ASC 为升序(从小到大)

– DESC 为降序(从大到小)

– 默认为 ASC

排序时,NULL 视为比任何值都小,升序出现在最上面

单字段排序
SELECT name, qq FROM students ORDER BY qq DESC;
多字段排序
SELECT name, shuxue, yingyu, yuwen FROM exam_result ORDER BY shuxue DESC, yingyu, yuwen; 

多字段排序具有优先级,对orderby后的第一个字段进行设定的排序,若第一个字段值相等

则利用第二个字段设定的顺序进行比较

然后对第一个字段的排列,如果第二个字段的值也相等,则进行第三个字段的比较,再进行第一个字段的排列

总的来说,实际上排列的只是orderby后的第一个字段,后面的比较都是为了第一个字段值相等时的情况服务的

使用表达式,别名
SELECT name, yuwen + yingyu + shuxue FROM exam_result  ORDER BY yuwen + yingyu + shuxue DESC; 

SELECT name, yuwen + yingyu + shuxue 总分 FROM exam_result   ORDER BY 总分 DESC; 
筛选分页结果
-- 起始下标为 0
 
-- 从 0 开始,筛选 n 条结果 
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
 
-- 从 s 开始,筛选 n 条结果 
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
 
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
-- 从 s 开始,筛选 n 条结果,相对其他语法清晰
-- 偏移量算法: pageSize * (PageNumber-1)pageSize:一页多少条 PageNumber:多少页

建议:对未知表进行查询时,好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死

LIMIT m,n : 表示从第m+1条开始,取n条数据;

LIMIT n : 表示从第0条开始,取n条数据,是limit(0,n)的缩写。

Update

对查询到的结果进行列值更新

UPDATE table_name SET column = expr [, column = expr ...]    
[WHERE ...] [ORDER BY ...] [LIMIT ...]
更新值为具体值
一次更新一个列
UPDATE table_name SET column = expr WHERE name = 'value'; 
一次更新多个列
UPDATE table_name SET column = expr, column = expr ...  WHERE name = 'value'; 
更新值在原值基础上变更

例如:给数学成绩加30分

-- 查看原数据 
SELECT name, shuxue, yuwen + shuxue + yingyu 总分 FROM exam_result    ORDER BY 总分 LIMIT 3; 
+-----------+--------+--------+ 
| name      | shuxue | 总分   | 
+-----------+--------+--------+ 
| 宋公明     |     65 |    170 | 
| 刘玄德     |     85 |    185 | 
| 曹孟德     |     60 |    197 | 
+-----------+--------+--------+

 -- 数据更新,不支持 shuxue += 30 这种语法 *********
 UPDATE exam_result SET shuxue = shuxue + 30    ORDER BY yuwen + shuxue + yingyu LIMIT 3;    -- 查看更新后数据 
 -- 思考:这里还可以按总分升序排序取前 3 个么?  不可以 因为更新后总分已经发生改变
 SELECT name, shuxue, yuwen + shuxue + yingyu 总分 FROM exam_result    WHERE name IN ('宋公明', '刘玄德', '曹孟德'); 
 +-----------+--------+--------+ 
 | name      | shuxue | 总分   |
 +-----------+--------+--------+ 
 | 曹孟德     |     90 |    227 | 
 | 刘玄德     |    115 |    215 | 
 | 宋公明     |     95 |    200 | 
 +-----------+--------+--------+ 
 3 rows in set (0.00 sec)
 
-- 按总成绩排序后查询结果 
SELECT name, shuxue, yuwen + shuxue + yingyu 总分 FROM exam_result    ORDER BY 总分 LIMIT 3; 
+-----------+--------+--------+ 
| name      | shuxue | 总分   | 
+-----------+--------+--------+ 
| 宋公明     |     95 |    200 | 
| 刘玄德     |    115 |    215 | 
| 唐三藏     |     98 |    221 | 
+-----------+--------+--------+ 
3 rows in set (0.00 sec)

注意: 没有 WHERE 子句,则更新全表 慎用!!!!

Delete

DELETE FROM  table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]

注意:delete删除之后,自增id也会在原值上增长

删除整表操作要慎用!delete删除整表数据并不会删除表结构

截断表
TRUNCATE [TABLE] table_name

注意:此操作慎用

Delete和Truncate的区别:

delete:

​ 1.可以根据条件删除部分数据

​ 2.可以删除整个表的数据,返回删除的记录数

​ 3.相对truncate速度慢

​ 4.不会重置auto_increment的值

truncate:

​ 1.只能对整表操作,不能像 DELETE 一样针对部分数据操作;

​ 2.实际上 MySQL 不对数据操作,所以比 DELETE 更快

​ 3.会重置 AUTO_INCREMENT 项

插入查询结果

INSERT INTO table_name [(column [, column ...])] SELECT ...

案例:删除表中的重复记录,重复的数据只能有一份

实现步骤:

​ 1.创建一个跟原表一模一样的结构的表

第一种方式:

show create table table_name;
 -- 查询表结构,重新创建一个一样的表

第二种方式:

create table 新表名 like 原表名;

​ 2.查询原表的数据,并且去重

select distinct id,name from 原表;

​ 3.查询原表去重的数据插入到新表

insert into 新表名(id,name)select distinct id,name from 原表;

​ 4.删除原表

drop table 原表名;

​ 5.讲新表名字改为原表名

alter table 新表名 rename to 原表名;

聚合函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGdaWPF0-1585360158459)(F:\courseware_note\MySQL课件\function.PNG)]

注意:使用*做统计,不受NULL影响。

​ 用列做统计,受NULL影响。

group by子句(分组查询)

select column1, column2, .. from table group by column;

案例:

准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)

​ EMP员工表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NqQtFL2V-1585360158459)(F:\courseware_note\MySQL课件\emp.png)]

​ DEPT部门表

​ SALGRADE工资等级表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSBGXkJT-1585360158460)(F:\courseware_note\MySQL课件\dept.png)]

显示每个部门的平均工资和最高工资

select deptno,avg(sal),max(sal) from EMP group by deptno;

每个部门的每种岗位的平均工资和最低工资

 select avg(sal),min(sal),job, deptno from EMP group by deptno, job;

显示平均工资低于2000的部门和它的平均工资 having和group by配合使用,对group by结果进行过滤

select avg(sal) as myavg from EMP group by deptno having myavg<2000;

内置函数

日期函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D2FEwFbO-1585360158461)(F:\courseware_note\MySQL课件\date.PNG)]

案例:创建一个留言表

mysql> create table msg (
    ->  id int primary key auto_increment,    
    ->  content varchar(30) not null,    
    ->  sendtime datetime    
    -> );

显示所有留言信息,发布日期只显示日期,不用显示时间

select content,date(sendtime) from msg;

查询在2分钟内发布的帖子

select * from msg where date_add(sendtime, interval 2 minute) > now();

字符串函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jlf2i8NC-1585360158461)(F:\courseware_note\MySQL课件\String.PNG)]

显示student表中的信息,显示格式:“XXX的语文是XXX分,数学XXX分,英语XXX分”

select concat(name, '的语文是',chinese,'分,数学是',math,'分') as '分数' from student;

注意:length函数返回字符串长度,以字节为单位。如果是多字节字符则计算多个字节数;如果是单字 节字符则算作一个字节。比如:字母,数组算作一个字节,中文表示多个字节数(与字符集编码有关)

以首字母小写的方式显示所有员工的姓名

-- 分析SMITH -> sMITH

-- SMITH -> S ->s
-- s MITH ->sMITH
-- 要用到 subString concat lcase
select concat(lcase(substring(ename, 1, 1)),substring(ename,2)) from EMP;

数学函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DdSei15i-1585360158462)(F:\courseware_note\MySQL课件\Math.PNG)]

其他函数

user() 查询当前用户

md5(str)对一个字符串进行md5摘要,摘要后得到一个32位字符串

database()显示当前正在使用的数据库

password()函数,MySQL数据库使用该函数对用户加密

ifnull(val1, val2) 如果val1为null,返回val2,否则返回val1的值

ifnull(null,null)结果也为null,是第二个null

-- 计算出员工的年薪(包含奖金),但是部分员工奖金为null
select ename,sal*12+comm from emp;
-- 无奖金的员工得到的年薪结果都为null null参与运算都为null
select ename,sal*12+ifnull(comm,0) from emp;
练习

​ 查找字符串’10,A,B’ 中逗号’,'出现的次数cnt

select length('10,A,B')-length((replace('10,A,B',',',''))) as cnt;

复合查询(重点)

多表查询

雇员名、雇员工资以及所在部门的名字

-- 因为上面的数据来自EMP和DEPT表,因此要联合查询
select * from EMP,DEPT
-- 其实我们只要emp表中的deptno = dept表中的deptno字段的记录
select EMP.ename, EMP.sal, DEPT.dname from EMP, DEPT where EMP.deptno = DEPT.deptno;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pzLNaV37-1585360158463)(F:\courseware_note\MySQL课件\tables.png)]

显示各个员工的姓名,工资,及工资级别

select ename, sal, grade from EMP, SALGRADE where EMP.sal between losal and hisal;

自连接

指在同一张表连接查询

显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)

方式一:子查询

select empno,ename from emp where emp.empno=(select mgr from emp where ename='FORD');

方式二:多表查询(自查询)

-- 使用到表的别名 
select leader.empno,leader.ename from emp leader, emp worker where leader.empno = worker.mgr and worker.ename='FORD';
-- 利用别名将一个表当两个表进行多表查询,也叫自连接

子查询(嵌套查询)

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

单行子查询

指子查询只返回单列,单行数据;

显示SMITH同一部门的员工

select * from EMP WHERE deptno = (select deptno from EMP where ename='smith');
多行子查询

返回单列多行数据

in关键字

查询和10号部门的工作相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的

select ename,job,sal,empno from emp where job in (select distinct job from emp where deptno=10) and deptno<>10;
all关键字

显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

select ename, sal, deptno from EMP where sal > all(select sal from EMP where deptno=30);
select ename, sal, deptno from EMP where sal > (select max(sal) from EMP where deptno=30);
any关键字

显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号

select ename, sal, deptno from EMP where sal > any(select sal from EMP where deptno=30);
多列子查询

指查询返回多个列数据的子查询语句

案例:查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人

select ename from EMP where (deptno, job)=(select deptno, job from EMP where ename='SMITH') and ename <> 'SMITH'; 
在from子句中使用子查询

子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。

显示高于自己部门平均工资的员工的姓名、部门、工资、平均工资

select ename, deptno, sal, format(asal,2) from EMP,(select avg(sal) asal, deptno dt from EMP group by deptno) tmp where EMP.sal > tmp.asal and EMP.deptno=tmp.dt;

查找每个部门工资最高的人的姓名、工资、部门、最高工资

select EMP.ename, EMP.sal, EMP.deptno, ms from EMP, (select max(sal) ms, deptno from EMP group by deptno) tmp  where EMP.deptno=tmp.deptno and EMP.sal=tmp.ms;

显示每个部门的信息(部门名,编号,地址)和人员数量

方法1:使用多表(缺点:求出多表的笛卡尔积再过滤)

select DEPT.dname, DEPT.deptno, DEPT.loc,count(*) '部门人数' from EMP, DEPT where EMP.deptno=DEPT.deptno group by DEPT.deptno,DEPT.dname,DEPT.loc;

方法2:使用子查询

-- 1. 对EMP表进行人员统计
select count(*), deptno from  EMP group by deptno; 
-- 2. 将上面的表看作临时表 
select DEPT.deptno, dname, mycnt, loc from DEPT, (select count(*) mycnt, deptno from  EMP group by deptno) tmp where DEPT.deptno=tmp.deptno;
合并查询

为了合并多个select的执行结果,可以使用集合操作符 union,union all。(相同子集才可以合并)

union

用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。

案例:将工资大于2500或职位是MANAGER的人找出来

 select ename, sal, job from EMP where sal>2500 union     
 select ename, sal, job from EMP where job='MANAGER';
union all

于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

 select ename, sal, job from EMP where sal>2500 union all    
 select ename, sal, job from EMP where job='MANAGER'; 

应用场景:

​ 复杂的查询拆分

​ 查的结果来自不同表

表的内连和外连(重点)

内连接

接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,之前用的都是内连接的简写形式

-- 标准写法
select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

显示SMITH的名字和部门名称

-- 用前面的写法 
select ename, dname from EMP, DEPT where EMP.deptno=DEPT.deptno and ename='SMITH';
 
-- 用标准的内连接写法 
select ename, dname from EMP inner join DEPT on EMP.deptno=DEPT.deptno and ename='SMITH';

外连接

左外连接

以左表为基准,左表完全显示

select 字段名  from 表名1 left join 表名2 on 连接条件
右外连接

以右表为基准,右表完全显示

select 字段 from 表名1 right join 表名2  on  连接条件;

案例

-- 建两张表 
-- 学生表
create table stu (id int, name varchar(30)); 
insert into stu values(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono'); 
-- 成绩表 
create table exam (id int, grade int); 
insert into exam values(1, 56),(2,76),(11, 8);

查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来

-- 当左边表和右边表没有匹配时,也会显示左边表的数据 右表数据为null
select * from stu left join exam on stu.id=exam.id; 

对stu表和exam表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应,也要显示出来

select * from stu right join exam on stu.id=exam.id;

左外连接和右外连接可以相互转换

列出部门名称和这些部门的员工信息,同时列出没有员工的部门

-- 左外连接 
select d.dname, e.* from dept d left join emp e on d.deptno=e.deptno; 
-- 右外连接
select d.dname, e.* from emp e right join dept d on d.deptno=e.deptno;

索引特性(重点)

InnoDB 不支持 全文索引

Memory 不支持 全文索引、聚合索引

MyISAM 不支持 哈希索引、聚合索引

索引:提高数据库的性能 以插入、更新、删除的速度为代价(因为还需要往二叉树里写入数据) 提高数据的检索速度

三个不用:不用加内存,不用改程序,不用调SQL

只要执行正确的create index 查询速度就能提高成百上千倍

常见索引

主键索引(primary key)

唯一索引(unique)

普通索引(index)

全文索引(fulltext)–解决中子文索引问题。

基本原理

没有索引的表进行整表扫描

表中添加索引之后,索引会形成一个二叉树,索引利用二分查找

添加索引之后时间复杂度由O(n)变为O(log n)

索引说明

索引占用磁盘空间,以空间换时间

当添加一条记录,除了添加到表中,还要维护二叉树,速度有影响,但不大

当我们添加一个索引,不能够解决所有查询问题,需要分别给字段建立索引;(只会对加了索引的字段提高检索效率)

alter table EMP add index(empno);

创建索引

创建主键索引

第一种方式

-- 在创建表的时候,直接在字段名后指定 primary key 
create table  user1(id int primary key, name varchar(30));

第二种方式

-- 在创建表的最后,指定某列或某几列为主键索引 
create table  user2(id int, name varchar(30), primary key(id)); 

第三种方式

create table  user3(id int, name varchar(30)); 
-- 创建表以后再添加主键 alter table user3 add primary key(id);
主键索引的特点

一个表中,最多有一个主键索引,当然可以使符合主键

主键索引的效率高(主键不可重复)

创建主键索引的列,它的值不能为null,且不能重复

主键索引的列基本上是int (约定)

创建唯一索引

三种方式同主键索引

唯一索引的特点

一个表中,可以有多个唯一索引

查询效率高

如果在某一列建立唯一索引,必须保证这列不能有重复数据

如果一个唯一索引上指定not null,等价于主键索引

普通索引的创建

第一种方式

create table user8(id int primary key,
                   name varchar(20),
                   email varchar(30),
                   index(name)
                   -- 在表的定义最后,指定某列为索引 
                  );

第二种方式

create table user9(id int primary key,  name varchar(20),  email varchar(30)); 
alter table user9 add index(name); 
-- 创建完表以后指定某列为普通索引

第三种方式

create table user10(id int primary key,  name varchar(20),  email varchar(30)); 
-- 创建一个索引名为 idx_name 的索引    
create index idx_name on user10(name);
普通索引的特点

一个表中可以有多个普通索引,普通索引在实际开发中用的比较多

如果某列需要创建索引,但是该列有重复的值,那么我们就应该使用普通索引

全文索引的创建

MYSQL提供全文索引机制,但是存储引擎必须是MyISAM,默认只支持英文,

如果想对中文进行全文检索,使用sphinx的中文版(coreseek)

java领域中中使用搜索引擎一般用Solr(底层是Lucene(一个搜索库))

大数据领域中使用搜索引擎一般用Elasticsearch(底层也是Lucene)

CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    title VARCHAR(200),
    body TEXT,
    FULLTEXT (title,body)
)engine=MyISAM;
INSERT INTO articles (title,body) VALUES('MySQL Tutorial','DBMS stands for DataBase ...'),    ('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');

explain工具(查看数据库的执行过程,经常用到的数据库优化工具)

explain select * from articles where body like '%database%'\G   
-- \G 将查询结果进行按列打印,可以使每个字段打印到单独的行。
*************************** 1. row ***************************
					id: 1
					select_type: SIMPLE
					table: articles
					type: ALL possible_keys: NULL
					key: NULL  <== key为null表示没有用到索引      
					key_len: NULL          
					ref: NULL         
					rows: 6        
					Extra: Using where 1 row in set (0.00 sec)
全文索引的使用
 -- MATCH AGAINST
 -> SELECT * FROM articles    
 -> WHERE MATCH (title,body) AGAINST ('database');
 *************************** 1. row ***************************
 					id: 1  
 					select_type: SIMPLE
 					table: articles
					type: fulltext 
 					possible_keys: title
 					key: title <= key用到了title      
 					key_len: 0          
 					ref:          
 					rows: 1        
 					Extra: Using where

查询索引

第一种方法

show keys from 表名;

第二种方法

show index from 表名; 

第三种方法(信息比较简略)

 desc 表名;

删除索引(类比索引的创建)

第一种方法(删除主键索引)

alter table 表名 drop primary key; 

第二种方法

 alter table 表名 drop index 索引名; 

第三种方法

 drop index 索引名 on 表名 ;

索引创建原则

比较频繁作为查询条件的字段应该创建索引

唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件(例如:性别)

更新非常频繁的字段不适合作创建索引 (更新频繁需要频繁维护索引,频繁更新效率会更低)

不会出现在where子句中的字段不该创建索引(不会用来检索的字段加索引没有意义)

事务管理

事务就是一组DML语句组成

这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。

(例如转账给他人50,你的账户扣款50的同时他人账户收款50才算成功)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2NVpN9qj-1585360158464)(F:\courseware_note\MySQL课件\transaction.jpg)]

事务的基本操作

开启事务

start transaction; 

创建保存点

savepoint 保存点名;

回到保存点(根据具体情况)

rollback to 保存点名;
注意事项

如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)

如果一个事务被提交了(commit),则不可以回退(rollback) (建议cheak后再commit)

同理,rollback之后也不能commit,因为rollback 和 commit后 事务都结束了

rollback to 可以选择回退到哪个保存点 rollback to之后可以commit,rollback to 只是回到了某一保存点

InnoDB支持事务,MyISAM不支持事务

开始事务可以使 start transaction

事物的隔离级别

场景:多个客户端同时操作某张表,如何进行隔离操作(保证数据的一致性)

无隔离性的问题
脏读

是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务

也访问这个数据,然后使用了这个数据。

即一个事务读到了另一个事务没有提交的数据。

不可重复读

是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。

在第一 个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不

一样的。这样就 发生了在一个事务内两次读到的数据是不一样的

即不能读到相同的数据内容

解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题

幻读

是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中

的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发

生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题

不可重复读的重点是修改:同样的条件, 你读取过的数据,再次读取出来发现值不一样了

幻读的重点在 于新增或者删除:同样的条件, 第1次和第2次读出来的记录数不一样

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjGWHskN-1585360158464)(F:\courseware_note\MySQL课件\tran.png)]

设置事务的隔离级别
set session transaction isolation level read uncommitted; -- 设置事务隔离级别为读未提交
查看事务的隔离级别
select @@tx_isolation; -- 默认事务隔离级别为可重复读(repeatable read)

可串行化案例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hcINWbp8-1585360158465)(F:\courseware_note\MySQL课件\serializable.png)]

DBMS:数据库管理系统

事务的ACID特性

原子性

事务是应用中最小的执行单位,就如原子是自然界的最小颗粒,具有不可再分的特征一样,事务是应用中不可再分

的最小逻辑执行体。

一致性

事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果

时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库

所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证

的。

隔离性

各个事务的执行互不干扰,任意一个事务的内部操作对其他并发事务都是隔离的。也就是说,并发执行的事务之间

不能看到对方的中间状态,并发执行的事务之间不能互相影响。

持久性

持久性是指一个事务一旦被提交,它对数据库所做的改变都要记录到永久存储其中(如:磁盘)。

视图

视图是一个虚拟表,其内容由查询定义。

视图包含一系列带有名称的列和行数据。视图的数据变 化会影响到基表,基表的数据变化也会影响到视图。

基本使用

创建视图
create view 视图名 as select语句;
删除视图
drop view 视图名;
视图的意义

可以简化查询,提高了重用性

对数据库重构,却不影响程序的运行

提高了安全性能。可以对不同的用户,设定不同的视图。

让数据更加清晰,想要什么样的数据,就创建什么样的视图

视图的规则和限制

与表一样,必须唯一命名(不能出现同名视图或表名)

创建视图数目无限制,但要考虑复杂查询创建为视图之后的性能影响 视图不能添加索引,也不能有关联的触发器

或者默认值

视图可以提高安全性,必须具有足够的访问权限

order by 可以用在视图中,但是如果从该视图检索数据 select 中也含有 order by ,那么该视图中的 order by 将被

覆盖

视图可以和表一起使用

用户管理

用户

用户信息

MySQL中的用户,都存储在系统数据库mysql的user表中

mysql> select host,user,authentication_string from user;
+-----------+---------------+-------------------------------------------+
| host      | user          | authentication_string                     | 
+-----------+---------------+-------------------------------------------+
| localhost | root          | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| localhost | mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | mysql.sys     | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | 
+-----------+---------------+-------------------------------------------+

字段解释:

host:表示这个用户可以从哪个主机登陆,如果是localhost,表示只能从本机登陆

user:用户名 authentication_string:用户密码通过password函数加密后的

*_priv:用户拥有的权限

创建用户
create user '用户名'@'登陆主机/ip' identified by '密码';
删除用户
drop user '用户名'@'主机名'

只写用户名,不写主机名,不能删除,它默认是%,%表示所有地方可以登录的用户

修改用户密码
自己改自己密码
set password=password('新的密码');
root用户修改指定用户密码
set password for '用户名'@'主机名'=password('新的密码');

数据库的权限

MySQL数据库提供的权限列表:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MJBQb0gv-1585360158466)(F:\courseware_note\MySQL课件\list.png)]

给用户授权 grant

刚创建的用户没有任何权限。需要给用户授权。

grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码']

权限列表:

grant select on ...
 
grant select, delete, create on ....
 
grant all [privileges] on ... -- 表示赋予该用户在该对象上的所有权限

*. * 代表本系统中的所有数据库的所有对象(表,视图,存储过程等)

库.* : 表示某个数据库中的所有数据对象(表,视图,存储过程等) identified by可选。

如果用户存在,赋予权限的同时修改密码,如果该用户不存在,就是创建用户

-- root 给 litao 赋予账户查询mytest库的DEPT表的权限 
mysql> grant select on mytest.DEPT to 'litao'@'localhost'; 

如果发现赋权限后,没有生效,执行如下指令:(数据库的权限在内存中放着,可能没有及时刷新)

flush privileges;
-- flush不成功可以退出用户重新登陆
回收权限 revoke
revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置';

-- 回收litao对数据库的所有权限 
revoke all on mytest.DEPT from 'litao'@'localhost';
面试题

SQL查询中各个关键字的执行先后顺序 from > on> join > where > group by > with > having > select > distinct > order by > limit

在MySQL中有例外:having后可以使用别名。

Java的JDBC编程

简介

​ JDBC(Java DataBase Connectivity,Java数据库连接)技术的简称,是一种用于执行SQL语句的Java

API(由 java.sql.,javax.sql. 包中的一些类和接口组成)。使数据库开发人员能够用纯Java API 来编写数据库应

用程序。

工作原理

JDBC 为多种关系数据库提供了统一访问方式

真正的数据库访问操作实现是由各自数据库厂商提供的。通常把厂商提供的特定于数据库的访问API称为数据库

JDBC驱动程序。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-INsgpDTZ-1585360158467)(F:\courseware_note\MySQL课件\JDBC.png)]

使用步骤

命令行中使用MYSQL的步骤

链接数据库(地址,端口,用户名,密码)

使用数据库

创建SQL命令(语句)

执行

返回结果

显示到控制台(结果处理)

断开连接

JDBC使用流程

java:方法通过对象来调用,对象通过类实例化

数据库操作的步骤进行面向对象的抽象(JDBC API)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yz3aY1zJ-1585360158468)(F:\courseware_note\MySQL课件\JDBC_lc.png)]

  1. 加载驱动(pom文件中配置MySQL驱动程序,通过Class加载驱动类)

    Class.forName("com.mysql.jdbc.Driver");
    
  2. 创建连接

    Connection connection = DriverManager.getConnection(url)
    

    JDBC规范中对url的定义:

    ​ <databasePrdductName>:Mysql ->mysql H2->h2 Oracle->oracle

    jdbc:<databasePrdductName>://host:port/<databaseName>?param1=value1&param2=value2

    String url = "jdbc:mysql://127.0.0.1:3306/memo?user=root&password=123456&useSSL=false";
    -- 用户名密码也可在DriverManager.getConnection(url,user,password);中指定
    

    3.准备SQL语句

    String sql = "select id,name,create_time,modify_time from memo_group";
    -- 写清楚列名,不要用*
    

    4.创建命令

    Statement statement = connection.createStatement();
    

    5.执行命令

    ResultSet resultSet = Statement.executeQuery(sql);
    

    6.处理结果

    While(resultSet.next()){
    // 每次执行next如果返回true,定位到数据库记录的下一条
    // getXxx(int)通过查询结果记录的列的下标取值(从1开始),不建议采用这种方式
    // 用getXxx(String)用列名
    	 int id = resultSet.getInt("id");
         String name = resultSet.getString("name");
         LocalDateTime createdTime = resultSet.getTimestamp("created_time").toLocalDateTime();
    //Timestamp ->(toLocalDateTime()) LocalDateTime
    //LocalDateTime ->(Timestamp.valueOf()) Timestamp
         LocalDateTime modifyTime = resultSet.getTimestamp("modify_time").toLocalDateTime();
         System.out.println(id + " " + name + " " + createdTime + " " + modifyTime);
     }
    

    7.关闭结果集

    resultSet.close();
    

    8.关闭操作命令

    statement.close();
    

    9.关闭连接

    connection.close();
    

    类似于模板设计模式 通过变化SQL语句,执行命令和结果处理,来完成插入,更新,删除操作

    在finally块中关闭结果集,操作命令,连接或者使用try-with-resources方式自动关闭资源

    try (
                        Connection connection = DriverManager.getConnection(url);
                        Statement statement = connection.createStatement();
                        ResultSet resultSet = statement.executeQuery(sql);
                ) {...}
    

    resultSet,statement,connection都实现了AutoCloseable接口,可以自动关闭

    模板设计模式实现JDBC开发

    模板设计模式+函数接口实现JDBC开发

    JDBC常用接口和类

    JDBC API

    掌握Java JDBC API (位于 java.sql 包下) 即可掌握Java数据库编程。

    数据库连接

    获取Connection对象通常有两种方式:

    ​ 一种是通过DriverManager的静态方法获取

    ​ 一种是通过DataSource(数据源)对象获取。

    实际应用中会使用DataSource对象。

    数据源:可以复用连接的数据库连接池

    statement对象

    Statement对象主要是将SQL语句发送到数据库中。JDBC API中主要提供了三种Statement对象。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BSSG1XFL-1585360158468)(F:\courseware_note\MySQL课件\statement.png)]

    预编译命令

    将Statement变为PrepareStatement,传入sql,执行命令的时候不传入sql

    PrepareStatement statement = connection.prepareStatement(sql);
    ResultSet resultSet = Statement.executeQuery();
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bIMtSRz-1585360158469)(F:\courseware_note\MySQL课件\goodstate.png)]

hile(resultSet.next()){
// 每次执行next如果返回true,定位到数据库记录的下一条
// getXxx(int)通过查询结果记录的列的下标取值(从1开始),不建议采用这种方式
// 用getXxx(String)用列名
int id = resultSet.getInt(“id”);
String name = resultSet.getString(“name”);
LocalDateTime createdTime = resultSet.getTimestamp(“created_time”).toLocalDateTime();
//Timestamp ->(toLocalDateTime()) LocalDateTime
//LocalDateTime ->(Timestamp.valueOf()) Timestamp
LocalDateTime modifyTime = resultSet.getTimestamp(“modify_time”).toLocalDateTime();
System.out.println(id + " " + name + " " + createdTime + " " + modifyTime);
}


7.关闭结果集

```java
resultSet.close();

8.关闭操作命令

statement.close();

9.关闭连接

connection.close();

类似于模板设计模式 通过变化SQL语句,执行命令和结果处理,来完成插入,更新,删除操作

在finally块中关闭结果集,操作命令,连接或者使用try-with-resources方式自动关闭资源

try (
                    Connection connection = DriverManager.getConnection(url);
                    Statement statement = connection.createStatement();
                    ResultSet resultSet = statement.executeQuery(sql);
            ) {...}

resultSet,statement,connection都实现了AutoCloseable接口,可以自动关闭

模板设计模式实现JDBC开发

模板设计模式+函数接口实现JDBC开发

JDBC常用接口和类

JDBC API

掌握Java JDBC API (位于 java.sql 包下) 即可掌握Java数据库编程。

数据库连接

获取Connection对象通常有两种方式:

​ 一种是通过DriverManager的静态方法获取

​ 一种是通过DataSource(数据源)对象获取。

实际应用中会使用DataSource对象。

数据源:可以复用连接的数据库连接池

statement对象

Statement对象主要是将SQL语句发送到数据库中。JDBC API中主要提供了三种Statement对象。

[外链图片转存中…(img-BSSG1XFL-1585360158468)]

预编译命令

将Statement变为PrepareStatement,传入sql,执行命令的时候不传入sql

PrepareStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = Statement.executeQuery();

[外链图片转存中…(img-9bIMtSRz-1585360158469)]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章