-
数据库(DB)
1.是什么:
存储数据,管理数据的仓库。
结构:(库名)数据库—(表名)表—(内容)数据
2.常见的数据库分为:
关系型数据库: Oracle、MySQL、MariaDB(与MySQL同一作者,使用数据库引擎不同) 、SQLServer、Access
非关系型数据库: MongoDB、Redis、Solr、ElasticSearch、Hive、HBase(分布式使用较广)
3.sql语言:
3.1概念:
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。
是高级的非过程化编程语言,允许用户在高层数据结构上工作。
Sql语言文件扩展名为.Sql
3.2分类
DML(Data Manipulation Language)数据操纵语言
如:insert,delete,update,select(插入、删除、修改、检索)简称CRUD操新增Create、查询Retrieve、修改Update、删除Delete
DDL(Data Definition Language)数据库定义语言
如:create table之类
DCL(Data Control Language)数据库控制语言
如:grant、deny、revoke等,只有管理员才有相应的权限
DQL(Data Query Language)数据库查询语言
如: select 语法
注意:SQL不区分大小写
3.3 常用操作:
3.3.1对库操作:
建库:create database cgb2022 DEFAULT CHARACTER SET utf8;
删库:drop database cgb2022;
查看所有数据库:show databases;
修改数据库字符类型为utf8: alter database cgb21080 character set utf8;
如果出现中文出错,临时改当前窗口(本次连接)为中文:set names gbk;
3.3.2对表操作:
查看某个库表:先进入使用数据库:use 库名;
展示使用的库的所有表:show tables;
创建表:create table student(字段名 varchar (10 ),字段名 int(10));
查看某个表数据结构:desc 表名;
删除表:drop table 表名;
添加列:alter table 表名 add column 列名 字符类型(10);
3.3.2对数据操作:
查询某表下的所有数据:select*from 表名;
给表添加数据:insert into 表名 values(各列对应的数据,有几列写几列);
给表特定列添加数据:insert into 表名(列1,列2)values(列1数,列2数);
修改数据:update 表名 set 要修改的字段=新数据 where 判断的字段=1;
删除整行数据:Delete from表名where 要删除数据的字段=要删除的数and隔开;
3.3.3 drop、delete和truncate之间的区别
drop删除库或者表,数据和结构定义
delete和truncate只是删除表的数据
delete可以指定where条件,删除满足条件的记录,tuncate删除所有记录
对于自增字段的表,delete不会自增值清零,而truncate是把表记录和定义都删除了,然后重建表的定义,所以自增主键会重头开始计数
3.4数据类型
3.4.1命名规则
字段名必须以字母开头,尽量不要使用拼音
长度不能超过30个字符(不同数据库,不同版本会有不同)
不能使用SQL的保留字,如where,order,group
只能使用如下字符az、AZ、0~9、$ 等
Oracle习惯全大写:USER_NAME,mysql习惯全小写:user_name
多个单词用下划线隔开,而非java语言的驼峰规则
3.4.2字符
char长度固定,不足使用空格填充,最多容纳2000个字符,char(11)存储abc,占11位。查询速度极快但浪费空间
varchar变长字符串,最多容纳4000个字符,varchar(11)存储abc,只占3位。查询稍慢,但节省空间。Oracle为varchar2
大文本: 大量文字(不推荐使用,尽量使用varchar替代)
以utf8编码计算的话,一个汉字在u8下占3个字节
注:不同数据库版本长度限制可能会有不同
3.4.3数字
tinyint,int整数类型(int类型限制不住长度,所以也没必要设置)
float,double小数类型(double不能设置具体长度)
numeric(5,2) decimal(5,2)—也可以表示小数,表示总共5位,其中可以有两位小数
decimal和numeric表示精确的整数数字
3.4.4日期
date 包含年月日
time时分秒
datetime包含年月日和时分秒
timestamp时间戳,不是日期,而是从1970年1月1日到指定日期的毫秒数
3.4.5图片
blob 二进制数据,可以存放图片、声音,容量4g。早期有这样的设计。但其缺点非常明显,数据库庞大,备份缓慢,这些内容去备份多份价值不大。同时数据库迁移时过大,迁移时间过久。所以目前主流都不会直接存储这样的数据,而只存储其访问路径,文件则存放在磁盘上。
4.mysql: 我们使用的MariaDB是其孪生兄弟引擎不同
4.1服务器端:保存数据,它来处理具体数据维护,保存磁盘
Mysql server :数据存在Mysql server 的my.ini配置文件中
4.2客户端:操作数据,CRUD新增,修改,删除,查询
操作方法一(DOS命令):
第一种进入DOS方法:打开MariaDB软件下的Mysql Client 然后输入密码
第二种进入DOS方法:打开CMD,输入mysql -u用户名(-uroot) -p密码(-proot)
操作方法二(可视化工具):
SQLyog工具
5.SQLyog工具:管理数据库的可视化工具
5.1创建库
1.空白位置右键或ctrl+d
2.命名同时选择字符集 (DOS中的create database 名 DEFAULT CHARACTER SET utf8;
5.2创建表
1.对应库的表右键创建表。
2.填入前三列(列名,数据类型,长度)然后填入表名即可:类似于DOS中的create table 表名(字段名 varchar (长度),字段名 int);
5.3 插入数据记录
在表中相应位置双击即可键入。
注意:
存在多条sql语句时,如果存在分号;则所有语句都要用分号隔开,否则不执行,或者所有语句都不使用分号,执行单行语句时需要选取整行然后执行,或者使用分号与上下语句分开则不用选取整行。
6.字段约束
6.1主键约束:primary key
如果为一个列的字段添加了主键约束,那么这个列就是主键,主键的特点是值唯一且不能为空。通常情况下,每张表都会有主键。
例1:将id设置为主键:
创建一张表a时create table a( id int primary key );//声明字段id为主键约束:
此时字段id列记录数据时数据不能为null且值必须唯一。
例2:将id设置为主键,且进行主键自增(只有主键可以加自增自减)。
创建一张表b时create table b( id int primary key auto_increment );
INSERT INT b VALUE( 8 ); //id不可以为null
例3:给已存在的列添加主键自增
alter table 表名 modify 列名 int auto_increment;
录入数据时id值不需要再手动键入,初始值为1,当需要id值,数据库负责从AUTO_INCREMENT获取一个id值,作为主键值插入到表中,而且每次用完AUTO_INCREMENT值,都会自增1,即使前面的值删除,后面再键入时会按上一次自增后最大值继续自增(Oracle数据库中可以设置自增多少从何处自增,sql中不可以,因为系统已经设置好了)。
6.2非空约束:NOT NULL
如果为一个列添加了非空约束,那么这个列的值就不能为空,但可以重复。
例1:将id设置为主键自增,pwd 设置为非空约束:
CREATE TABLE c(
id INT PRIMARY KEY AUTO_INCREMENT,
pwd VARCHAR(10) NOT NULL);
执行INSERT INT c VALUE(NULL,’7’ ); // id可以为null,pwd不可以为null但可重复
6.3唯一约束:unique
如果为一个列添加了唯一约束,那么这个列的值就必须是唯一的(即不能重复),但可以为空。
create table d(
id int primary key auto_increment,
username varchar(50) unique);
执行INSERT INTO d VALUES(NULL,'8');// id可以为null, username可以为null,但不可以重复
6.4 默认约束:default
给字段使用default添加默认值。
create table e(
id int primary key auto_increment,
sex varchar(10) default "男" //添加性别列默认值为“男”。
);
6.5检查约束:check
给字段使用check添加合法性的检查。
create table f(
id int primary key auto_increment,
age int,
check (age<100) //设置age字段的检查依据。不符合要求就报错。
);
6.6 外键约束foreign key
通过两个表的主键描述两个表的关系,子表主键不可设置自增。
约束内容
1.子表主键的值需要取自主表(被包含于主表),添加的子表主键的值如果在主表中不存在则会报错。
2.主表删除主键数据时,对应的子表主键不存在,如果子表有对应的主键则会报错。
(1)创建主表
create table tb_user(
id int primary key auto_increment,
name varchar(20),
password varchar(20)
);
(2)创建子表
create table user_id_addr(
user_id int primary key ,
address varchar(100),
foreign key(user_id) references tb_user(id)
//添加外键约束格式:foreign key(本表主键名) references 对方表名(对方表主键)
);
7.基础函数
类似于java中的方法,也有()作为标记,主要也是用来提高SQL的效率,有的也要传递参数。
lower :select 列字段, lower (列字段或'指定内容') X from 表名; //数据转小写,()中为指定列字段或”指定内容”,输出后指定内容为小写。from前的X为给临时列字段命名为X。同理以下函数都可以。
upper : select列字段, upper (列字段或'指定内容') from表名; //数据转大写,()中为指定列字段或”指定内容”, 输出后指定内容为大写。
Length: select ename,LENGTH(ename),job,LENGTH(job) FROM 表名;//查询指定列各数据的长度,utf-8中每个汉字长度为3.
Substr:select ename,SUBSTR(ename,2,3) FROM表名; //从第2个字符开始截取3个字符。
select ename,SUBSTR(ename, 3) FROM表名; //从第3个字符开始截取剩下字符。
Concat:select ename,CONCAT(ename,123,"ABC") FROM表名;//拼接123和ABC,除了数字都需要加双引号。
Replace: select ename,replace(ename,'a','666') FROM表名;//替换ename列中a元素为666。
Ifnull:select IFNULL(comm,10) comm FROM tb_emp;// 判断如果comm列有NULL值则赋值为10 。
round :select ROUND(comm) from tb_emp;// comm列四舍五入只保留整数。
select comm,ROUND(comm,1) from tb_emp;// comm列四舍五入保留一位小数。
ceil和floor: select comm,ceil(comm) ,floor(comm) from tb_emp//ceil向上取整保留整数,floor向下取整保留整数。
Now:select now();//获取当前时间
select YEAR(now());//获取当前时间的年
select month(now());//获取当前时间的月
select day(now());//获取当前时间的日
select hour(now());//获取当前时间的时
select minute(now());//获取当前时间的分
select second(now());//获取当前时间的秒
select curdate()//获取年月日
select curtime()//获取时秒分
转义字符:\
'A'BC': 单引号是一个SQL语句的特殊字符,一对单引号中需要用单引号时需要在单引号前加转义符号\('A\'BC'),但是如果在双引号中使用单引号则不用转(“A'BC”)。
8条件查询:
distinct: select distinct 列字段名 from 表名;// 去除某列字段重复的数据
where:注意where判断里不能用别名,不能出现聚合函数。
select * from 表名where 数据判断条件 //查找某表指定条件的行数据。
select * from 表名 where empno =100;//在全部列数据中查找某表empno列数据为100的行的值。
select * from 表名 where empno >100;//在全部列数据中查找某表empno数据大于100的行的值。
select * from 表名 where 1=1;//在全部列数据中查找某表1=1(true)的行的值。
select * from 表名 where empno>100 and job="员工"; //在全部列数据中查找某表empno列数据大于100,且job=员工的行的值。
select * from表名where empno>100 or job="员工"; //在全部列数据中查找某表empno列数据大于100,或者job=员工的行的值。
select * from表名where sal in(10,20,30); //在全部列数据中查找某表sal =10或者20或者30的行数据。
select * from表名where sal not in(10,20,30); //在全部列数据中查找某表 sal不等于10或者20或者30的行数据。
like (像): 通配符%代表0到n个字符,通配符下划线_代表1个字符
select * from emp where ename like 'a%'; //以a开头的 (只有这种会让索引生效)
select * from emp where ename like '%a'; //以a结束的 (会让索引失效)
select * from emp where ename like '%a%'; //中间包含a的(会让索引失效)
select * from emp where ename like 'a_' ; //a后面有一个字符的(下划线_代表一个字符位置)
null数据处理:
使用 comm=null 无法查出含null值的数据行。
要查找记录为null的数据需要使用comm is null;
要查找记录为非null的数据需要使用comm is not null;
between...and:
select*from 表名where sal between 100 and 900 ;//查找100<=sal <=900的值,且顺序不能反。
limit n,m: 限制从n+1条开始查询展示m条 ,limit放在判断条件where后面
select * from emp limit 2;// --列出前两条
select * from emp limit 1,2;/ --从第1+1条开始,展示2条记录
select * from emp limit 0,3; /--从第0+1条开始,展示3条记录--前三条
order by:排序 , order by放在判断条件where后面
select * from emp order by sal //#默认升序 (sal 后面省略了ASC)
select * from emp order by sal desc// #降序(使用desc)
字母是按a~z的先后顺序,日期是按数字大小排序,中文是按编码表文字对应的数字。
统计案例
入职统计:统计2019年以后入职的
select*from tb_emp where year(hiredate)<2019;
select*from tb_emp where hiredate<2019-1-1;
年薪统计:(月薪+奖金)*13薪 如果源值有null 用ifnull(列,要换的值)
select sal,comm,(sal)*13+ifnull(comm,0)*13 year from tb_emp;
9聚合函数 aggregation:根据一列统计结果
count():统计一列数据个数
select count(sal) from tb_emp;//统计sal列数据个数, null值不被统计
select count(*) from tb_emp;//统计各列数据行数(低效)null值也统计
select count(1) from tb_emp;//统计各列数据行数(高效)null值也统计
max / min():统计最大值/最小值
select max(sal) from tb_emp;
select min(sal) from tb_emp;
select max(sal),min(sal) from tb_emp;
sum / avg():统计一列数据总值/平均值
select sum(sal) from tb_emp;
select avg(sal) from tb_emp;
select sum(sal),avg(sal) from tb_emp;
错误的查询方式:
select sal , min(sal) from tb_emp; // sal为非聚合列,min()为聚合列,混合查询会报错,或不报错出现错误数据,所以要进行分组group。
10.分组 group:
用于对查询的结果进行分组统计,group by表示分组, having 子句类似where过滤返回的结果
group by:对数据分组
select job ,avg(sal) from tb_emp group by job;//按job列不同类型分组统计,如果不使用group by job,则平均值默认是非聚合列第一个数据的类型。
select deptno, count(1) from tb_emp group by deptno;//按deptno列分类统计行数。
select year(hiredate),count(1) from tb_emp group by year(hiredate);//按年统计员工数。
select deptno,max(sal) from tb_emp group by deptno;//按部门分组,统计最大值。
having:分组后过滤
having和where后面都是判断条件,但是where是先判断过滤再统计,having是先统计再判断过滤,所以加在group by 后面 的是having。
select deptno,max(sal) from tb_emp group by deptno having max(sal)>8000;
尝试where和having互换:注意where判断里不能用别名,不能出现聚合函数。
//select count(1 ) , year(hiredate) a from emp where count(1)>1 group by a having count(1 )>1; //因where后面不能出现聚合函数所以无法判断。
11 select语句各部分顺序:
书写顺序是固定的:select ... from [on Expr] [where Expr] [group by] [having] [order by] [limit]
执行顺序:from -> 选择表
ON-> 链接条件
<join_type> JOIN-> 链接
where语句 -> 条件过滤
group by -> 分组
AGG_FUNC-> 聚合
having -> 分组过滤
select *| -> 开始查找
distinct column-> 选择字段、去重
order by -> 排序
limit->; 分页
12.事务 transaction
12.1事务是什么:
数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
就是将一堆的SQL语句(通常是增删改操作)绑定在一起执行,要么都执行成功,要么都执行失败,即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态。
12.2事务4个特性ACID
12.2.1概述
一般来说,事务必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中如果发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:底层使用同步锁保证数据安全,在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作,多线程下数据一致。
隔离性:底层使用同步锁保证数据安全,数据库允许多个并发事务同时对其数据进行读写和修改的能力,多线程同时执行互不干扰,但数据库每次只接受一个请求。
持久性:事务处理(增删改)结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
12.2.2隔离级别:四个
读未提交(Read uncommitted):安全性最差,可能发生并发数据问题,性能最好(解决幻读,幻读:在同一事务中,对同一张表的两次查询结果不一致。)
读提交(read committed): Oracle默认的隔离级别(预防脏读:在一个事务中读取到另外一个事务中未提交的结果。)
可重复读(repeatable read):MySQL默认的隔离级别,安全性较好,性能一般
(预防不可重复读,同一个事务中对同一数据的再次查询结果不一致)
串行化(Serializable): 表级锁,读写都加锁,效率低下,安全性高,不能并发(解决以上三种问题)
12.2.3mysql事物
MySQL默认的隔离级别是可重复读(repeatable read)
在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务,每一条SQL语句默认自带start transaction和commit。但如果需要在一个事务中包含多条SQL语句,那么需要手动输入开启事务start transaction和结束事务commit或rollback。
开启事务:start transaction;
在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起
点),然后可以去执行多条SQL语句
结束事务:commit(提交事务,完成数据库修改)或rollback(回滚事务,不修改)。
如果不输入结束事物语句,执行的语句在临时区不会对真正的数据库产生影响,如果输入commit结束事物语句,则会让临时区语句对真正的数据库产生影响,如果输入rollback结束语句则临时区的语句会撤销,也不会对真正的数据库产生影响,回到开启事物状态。
13.索引 index
13.1定义:
排好序的快速查找的数据结构,拥有特定查找算法,高效但是会单独生成一张表,额外独自占据大量内存空间。
13.2分类:
单值索引:一个索引只包括一列(一个字段),一个数据表可以有多个列被索引。
唯一索引:被索引的列需要受到唯一约束;主键会自动创建唯一索引。
复合索引:一个索引可以同时索引多列(多个字段),但使用时遵循最左原则。
13.3 怎么用
13.3.1 查询索引:
show index from 表名;
查询是否使用了索引:
explain select job from tb_emp where job="员工" ;
13.3.2 创建单值索引:
create index 索引名 on 表名(被索引列)
13.3.3 创建唯一索引:
create unique index 索引名 on 表名(被索引列)
13.3.4 创建复合索引:
create index 复合索引名 on表名(被索引列1,被索引列2..);
最左原则:使用索引,使用时如果不包含被索引列1,则复合索引失效。
13.3.5 删除索引:
alter table 表名 drop index 索引名 ;
13.3.6添加索引:
alter table 表名 ADD index 索引名(字段)。//添加单值索引
alter table 表名 ADD FULLTEXT (字段); //添加全文索引
alter table 表名 ADD unique(字段); //添加唯一索引
13.4优缺点:
13.4.1优点:
1.索引是数据库优化
2.表的主键会默认自动创建索引
3.每个字段都可以被索引
4.大量降低数据库的IO磁盘读写成本,极大提高了检索速度
5.索引事先对数据进行了排序,大大提高了查询效率
13.4.2缺点:
1.索引本身也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也要占用空间
2.索引表中的内容,在业务表中都有,数据是重复的,空间是“浪费的”
3.虽然索引大大提高了查询的速度,但对数据的增、删、改的操作需要更新索引表信息,如果数据量非常巨大,更新效率就很慢,因为更新表时,MySQL不仅要保存数据,也要保存一下索引文件
4.随着业务的不断变化,之前建立的索引可能不能满足查询需求,需要消耗我们的时间去更新索引
14.视图:
14.1 作用:缓存了sql的执行结果,以视图呈现
14.2 创建视图:create view 视图名 as select*from 表名;
14.3 查看视图:左侧刷新后点击视图可查看视图表或者select*from 表名;
14.4 优点:简化查询sql(相同sql不必再写sql,直接查看视图就行)
视图可以被共享,视图屏蔽了真是业务表的复杂性。
缺点:视图一旦创建,SQL无法被优化。
15.表关联 association
15.1概念
表table代表了生活中一个主体,如部门表dept,员工表emp。表关联则代表了表之间的关系。
15.2多表联查 join:
多表查询是指基于两个和两个以上的表的查询。在实际应用中,查询单个表可能不能满足你的需求,如显示员工表emp中不只显示deptno,还要显示部门名称,而部门名称dname在dept表中。一对一,一对多,多对一,多对多。
- 笛卡尔积 Cartesian product
原理:
把多个表的数据都拼接起来,多表查询都是先生成笛卡尔积,再进行数据的筛选过滤。实际开发中尽量少用多表联查,其根本原因就是,查询过程中,先在内存中构建一个大大的结果集,然后再进行数据的过滤。那这个构建过程,和所使用的内存资源,包括过滤时的判断,都是既耗费资源,又浪费时间。
方法:
select * from 表1,表2 where 表1.字段a=表2.字段a ;//如果字段唯一可不用使用表.。
查询表1表2的内容,选取指定字段,列出选取的字段值相同的拼接在一起形成结果表,where后可使用and或者or增加多个过滤条件。
- 连接查询
原则:小表驱动大表,左边表一最好是小表。
内连接 inner join:结果取两表交集
select *from 表1 inner join表2 on tb_dept.`deptno`=tb_emp.`deptno`;//取两个表交集
左(外)连接 left join: 结果取左表所有,右表不满足的用null代替
select *from 表1 left join表2 on tb_dept.`deptno`=tb_emp.`deptno`;
右(外)连接 right join: 结果取右表所有,左表不满足的用null代替
select *from 表1 right join表2 on tb_dept.`deptno`=tb_emp.`deptno`;
- 子查询 subquery
子查询是指嵌入在其他select语句中的select语句,也叫嵌套查询。子查询执行效率低慎用。记录少时效率影响不大、图方便直接使用,记录多时最好使用其它方式替代。
16.数据库优化:
1.若需要经常查询就创建索引。
2.查看时使用视图。//视图数据完整保存源数据,屏蔽原表复杂性,具有公开性
3.录入数据时,内容尽量不使用中文。
4查看内容最好具体到字段,而不是使用*查询全部内容。
5.查看使用分页。
6.查看最好不要使用笛卡尔积进行多表联查而是连接查询。
7.插入多数据时最好使用一条语句。
17.DOS命令数据库备份与恢复
17.1备份
1.方法:在cmd窗口中未登录mysql状态下,运行mysqldump命令。
语法: mysqldump -uuName -pdbName > BackupPath
说明:
mysqldump: 备份命令
-uuName:用户名
-p:指密码,后不跟密码,回车后,cmd会提示输入密码。
dbName:要备份的数据库名。
>:重定向运算符,将左侧的文件内容copy到右侧文件
BackupPath
2.备份内容:
mysqldump 仅备份dbName中所有的表和表记录,但并不备份dbName本身。因此如果dbName本身也不存在时,恢复数据时,首先要建库,再恢复内容。
3.备份方法:
将数据库中表和表记录以sql语句的形式写到文件中。主要有删表、建表、插入记录语句等。
4.备份所有库:
语法:mysqldump -uuName -p --all-databases > BackupPath。
说明:并非所有mysql版本支持该语法。
与备份某一库的区别:备份所有库的文件中,会包含建库语句。
17.2恢复
1.方式一:在未登录mysql状态下的cmd窗口中,使用mysql命令。
语法:mysql -uuName -p dbName < BackupPath
说明:
mysql:恢复命令。
<:文件重定向,将右侧的文件内容copy到左侧文件。
2.方式二:在登录mysql状态下的cmd窗口下,使用source命令
语法:source BackupPath
3.恢复步骤:
第一步:创建库。
第二步:恢复库。
-
JDBC:JAVA与数据库连接规范
1.概述
概念:完成JAVA和数据库连接的技术
使用步骤:1.导入jar包。//JDBC提供的丰富的工具类
2.提供链接数据库的参数(用户名root,密码自定,端口号3306)
3.在JAVA程序中发起SQL语句操作数据库。
4.如果数据库右查到结果,返回到程序。
如何导入jar包:1.复制jar包到java内工作空间
2.java内右键jar包点击add.as.libery(能点开下级文件就是成功了)
2. 使用数据库步骤
2.1 .注册驱动
Class.forName("com.mysql.jdbc.Driver");//输入反射对象的全路径即可注册
2.2.获取数据库的连接(用户名/密码)
String url="jdbc:mysql://localhost:3306/cgb456";
解释:链接地址 "jdbc:mysql://ip地址:软件端口号/数据库名"
Connection c = DriverManager.getConnection(url, "root", "root");//链接地址,用户名,密码
防止中文乱码:url增加参数:characterEncoding=utf8
Stringurl="jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
2.3.获取传输器
Statement s = c.createStatement();
或PreparedStatement p = c.prepareStatement(sql);
2.3.1 Statement和PreparedStatement区别
(1) Statement是PreparedStatement的父接口
(2) Statement低效不安全PreparedStatement高效安全
(3)执行代码不同
Statement:
Statement s = c.createStatement();
String sql= "Select*from dept";
ResultSet r = s.executeQuery( sql );
PreparedStatement:
String sql="select * from tb_emp where deptno>? and mgr>?";
PreparedStatement p = c.prepareStatement(sql);
p.setInt(1,1); // 第1个? 传入1
p.setInt(2,100); // 第2个? 传入100
如果sql语句不需要传入值不需要上述两句set
ResultSet r = s.executeQuery( );
2.4.执行SQL
String sql= "Select*from dept"; //sql为要执行的sql语句
ResultSet r = s.executeQuery(sql);//用来执行查询的方法
int i = s.executeUpdate();//用来执行增删改,返回影响行数
2.5.处理数据库返回结果
使用循环语句把每个值获取。
while (r.next()){ //通过ResultSet的next方法判断是否有下一个数据
int a= r.getInt(1); //获取第一列的int值
System.out.println(a);
};
2.6.释放资源
r.close(); //关闭结果
p.close(); //关闭结果
s.close();//关机传输器
c.close();//关闭连接
2.7 JDBC常见问题
2.7.1 Class.forName这句话有用没?
Class.forName可以指定class类路径进行动态创建对象实例,可JDBC这句话没有返回对象啊,那写这句有什么作用呢?看看java.sql.Driver.class的源码就找到真相了,原来它用了静态代码块创建对象。
2.7.2 写了创建了,那不写呢?怎么不写也能执行呢?
Java提供了SPI机制,用户可以自行配置类,JDBC高版本驱动就都引入了这个支持。如果用户使用了Class.forName方式就自己指定了驱动,如果未写这句话,则Java自动去META-INF/services/java.sql.Driver文件中找启动类。
2.7.3不同版本的mysql需要不同版本的驱动
Mysql5.0x mysql-connector-java-5.1.32.jar
Mysql8.0x mysql-connector-java-8.0.21.jar
Driver变成了: com.mysql.cj.jdbc.Driver,中间多了cj
url必须加时区参数: serverTimezone=Asia/Shanghai
2.7.4中文乱码
url增加参数:characterEncoding=utf8防止中文乱码
String url ="jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8
&serverTimezone=Asia/Shanghai&useSSL=false";
3.jdbc总结
1, 什么是JDBC? java程序连接数据库的标准方案,全称是java database connectivity
2, 使用JDBC步骤? 导入jar包,注册驱动,获取数据库的连接,获取传输器,执行SQL,解析结果集(查询),关闭资源
3, 传输器Statement和PreparedStatement有什么区别? Statement不安全(可能发生SQL攻击),而且低效
4, Statement和PreparedStatement有什么关系? public interface PreparedStatement extends Statement ,是父子接口
5, SQL攻击? 原因是:SQL中出现了特殊符号#(注释符号)改变了SQL的语义 解决方案:使用新的传输器PreparedStatement
6, 执行SQL: 先执行SQL骨架,然后再给SQL设置参数
executeUpdate(): 用来执行增删改的SQL语句,并且返回了影响行数
executeQuery(): 用来执行查的SQL语句,并且返回了结果集ResultSet