mysql数据库基础

数据库

简单地说,救据库(英文Daabase)就是一个存放数据的仓库。在日常工作中,常常需要把等些相关的数据放进这样的仓库,并根据管理的需要进行相应的处理。

DBMS

数据库管理系统(DatabaseManagementSystem)是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称DBMS。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。用户通过DBMS
访问数据库中的数据,数据库管理员也通过dbms进行数据库的维护工作。它可使多个应用程序和用户用不同的方法在同时或不同时刻去建立,修改和询问数据库。大部分DBMS提供数据定义语言DDL(DataDefinitionLanguage)和数据操作语言DML(DataManipulationLanguage),供用户定义数据库的模式结构与权限约束,实现对数据的追加、删除等操作,以及数据库控制语言DCL(DataControlLanguage),用来设置或更改数据库用户或角色权限的语句

  • 数据库和DBMS不是同一个东西

mysql

安装

  1. 配置环境变量,bin目录配置mysql path

  2. 新建配置文件my.ini

    1
    2
    3
    4
    5
    [mysqld]
    basedir=G:\Loh\Code_usefile\mysql-8.0.32-winx64//配置目录
    datadir=G:\Loh\Code_usefile\mysql-8.0.32-winx64\data//配置data目录
    port=3306
    skip-grant-tables #(8.0版本需要注释掉该语句)
  3. 启动cmd,切换到bin目录,输入mysqld --install安装

  4. 输入mysqld --initialize-insecure --user=mysql初始化数据文件

  5. 输入net start mysql启动mysql后,需要以管理员身份运行,否则会报错:

  6. 输入mysql -u root -p密码(注意-p后不可以有空格)

  7. ```js
    update mysql.user set authentication string=password(‘123456’) where user=’root’ and Host=’localhost’
    #8.0版本用这个改密码alter user ‘root‘@’localhost’ identified by ‘123456’;
    #sqlyog用这个更新密码ALTER USER ‘root‘@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘password’(password改成要的密码)
    flush privileges

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17



    ![](mysql数据库基础/image-20230524193822898.png)



    **mysql关键字不区分大小写**

    # 数据库操作

    ## 数据库操作(了解)

    创建新数据库

    ```sql
    create database [if not exists] 数据库名;

删除数据库

1
drop database if exists 数据库名;

切换数据库

1
use 数据库名;

查看数据库

1
show databases;

关键字

  • create
  • drop

列类型

数值类型

类型 大小
TINYINT 1 Bytes
SMALLINT 2 Bytes
MEDIUMINT 3 Bytes
INT或INTEGER 4 Bytes 标准类型,存储int
BIGINT 8 Bytes
FLOAT 4 Bytes
DOUBLE 8 Bytes
DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 字符串形式浮点数,金融计算多使用

字符串类型

字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

类型 大小 用途
CHAR 0-255 bytes 定长字符串
VARCHAR 0-65535 bytes 变长字符串
TINYTEXT 0-255 bytes 短文本字符串
TEXT 0-65 535 bytes 长文本数据

注意:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。

CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。

有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

日期和时间类型

表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每个时间类型有一个有效值范围和一个”零”值,当指定不合法的MySQL不能表示的值时使用”零”值。

TIMESTAMP类型有专有的自动更新特性,将在后面描述。

类型 大小 ( bytes) 范围 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 ‘-838:59:59’/‘838:59:59’ HH:MM:SS 时间值或持续时间
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 ‘1000-01-01 00:00:00’ 到 ‘9999-12-31 23:59:59’ YYYY-MM-DD hh:mm:ss 混合日期和时间值
TIMESTAMP 4 ‘1970-01-01 00:00:01’ UTC 到 ‘2038-01-19 03:14:07’ UTC结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYY-MM-DD hh:mm:ss 混合日期和时间值,时间戳

null

空值,未知

字段属性(重点)

Unsigned:

  • 无符号整数
  • 声明该列不能为负数

Zerofill:

  • 0填充的
  • 不足的位数使用0来填充

自增:AUTO_INTCREMENT

  • 通常理解为自增,自动在上一条记录的基础上+1(默认)
  • 用来设计唯一主键index,必须是整数类型
  • 自定义设计主键自增的起始值和步长

非空 NULL not null

  • not null非空字段不赋值即报错
  • null,不填默认为null

默认

  • 设置默认值
  • sex 默认值为男,不填值则使用默认值

注释:COMMENT

  • 注释

创建表(重点)

创建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CREATE TABLE IF NOT EXISTS teacher( 
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT 'tid',
`name` VARCHAR(30) NOT NULL DEFAULT 'anonymous' COMMENT 'tname',
`psssword` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT 'tpwd',
`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT 'sex',
`brithday` DATETIME DEFAULT NULL COMMENT 'bornday',
`address` VARCHAR(100) DEFAULT NULL COMMENT 'address',
`email` VARCHAR(50) DEFAULT NULL COMMENT 'mail',
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4,COLLATE=utf8mb4_general_ci;




//CREATE TABLE [IF NOT EXISTS] 表名(
`字段名` 列类型 [字段属性] [索引] [注释],
`字段名` 列类型 [字段属性] [索引] [注释],
`字段名` 列类型 [字段属性] [索引] [注释],
[ PRIMARY KEY (`字段名`) ]
)[表类型] [字符集设置] [注释]

常用命令

逆向显示创建命令

假设有一个库和一张表

1
2
3
show create database `库名`; --查看库的定义
show create table `表名`; ---查看该表的定义
desc `表名` --显示表结构

数据库引擎

表操作

修改表结构

1)修改表名

rename 原表名 to 新表名

1
rename tb_txt to tb_txt_new;

2)修改列名

alter table 表名 rename column 列名 to

1
alter tb_txt_new rename column txtid to tid;

3)修改字段类型

alter table 表名 modify(字段类型)

1
alter table tb_txt_new modify(tid vachar2(20));

4)添加列

alter table 表名 add 字段类型

1
alter table tb_txt new add col_test name varchar2(30);

5)删除列

alter table 表名 drop column 字段

1
alter table tb_txt new drop column col_test name;

删除表

1
drop table

mysql数据管理

外键

创建表操作时不指定外键

DML(重点)

DML介绍

DML(DataManipulationlanguage数据操控语言)用于操作数据库对象中包含的数据。也就是说操作的单位是记录。

Oracle数据库的DML表数据的操作有三种

①insert(插入);②update(更新);③delete(删除)。

条件语句where

运算符类:>,<,>=….

between…and.. 在xx和xx之间的

and 等价与&&

or 或

插入insert

通过insert语句向指定的表中添加记录,添加记录时需要满足以下条件,类型和长度要兼容,(字段兼容值);值满足约束,主键(唯一+非空),非空(必填),唯一(不重复),默认(没有填写使用默认值),检查(满足条件),外键(参考主表主键列的值);个数必须相同,指定列,个数顺序与列
相同;没有指定,个数与表结构的列个数和顺序相同(nul也得占位,没有默认值)。

1
insert into 表名 [(字段列表)] values(值列表);

默认方式添加

insert into 表名 values(值列表)
此时的值列表顺序和个数以及类型需要和标结构一致,默认的,可以为空的列也都必须填上值。可以手写也可以从别的表中获取。

1
insert into tb_user values(1001'test''test123'null'女’,null,sysdate);
1
insert into tb_user_copy values(select * from tb_user);

添加时指定列和顺序

insert into表名(指定列)values(值列表)
此时的值列表要和指定的列个数、顺序、类型保持一致

1
insert into tb_user(username,userid,userpwd)values(tom,1002,tompwd);
1
insert into tb_user_copy(username,userid,userpwd) values(select username userid,userpwd from tb_user)

当添加的记录中,存在外键关联时需要注意,可以采取先查询后添加的方式

1
insert into tb_txt(txtid,title,userid)(1001,title1,123select userid from tb_user where username=随笔大师));

修改update

通过update语句可以更新(修改)表中的记录值。

update 表名 set 字段1=值1 [字段2=值2…] where 过滤行记录:

1
update tb_user set userpwd=8888 where 1=1;
1
update tb_user set userpwd=good , age=29 where username='zzz' and pwd='123'
1
update tb_userset(username, userpwd)=select  'good''block’ from dual) where userid=1;

删除delete

通过delete语句可以删除表中的记录。(注意存在主外键约束的记录)
delete from表名where条件;

1
delete from tb_user where userid<10;
1
delete from tb user;

删除表的方式

TRUNCATE

TRUNCATE 表名

TRUNCATE清空一个表,表结构和索引约束不会变

DQL查询数据(重中重)

select基本结构和简单查询

select结构

结构:

1
select * |colname  [,...] from table [alias]

分析:
select 关键字 后面跟要查询的内容from关键字后面跟数据的来源
解析步骤:1) from找来源 2) select挑数据
语法结构需记忆

简单查询

1)查询所有

1
select * from 表名;

2)查询部分字段

1
select1 , 列2 列n from 表名;

3)按顺序查询

1
select 自定顺序列1 , 自定顺序列2 from 表名;

去重、别名和排序

去重 distinct

去除重复记录
结构:

1
select distinct 列名 from 表名;

列别名

给列取名字
结构:

1
2
3
select 列名 改名 from 表名;
select 列名 as 改名 from 表名;
//多列在from前加,号再将列名 改名写上

排序 order by

将查询出来的结果按照指定顺序排序
结构:

1
select 列名1 , 列名2 from 表名 orer by 列名(要按此排序) desc(降序)/asc(升序);

多字段排序

1
select 列名1 , 列名2 from 表名 orer by 列名 desc(降序)/asc(升序),列名 desc(降序)/asc(升序);

空值可以在语句末尾加nulls firstnulls last

条件查询

当我们查询的数据需要经过筛选时,我们会给出一些条件,只有当表中的记录满足我们所给的条件,才会成为我们的目标数据,这就需要借助我们的条件查询。

1
select 查询内容 from 数据来源 where 行记录条件

运算符

条件运算

一般条件 = 、> 、< 、>= 、<= 、

都表示不等于 <>、!=、^=、

​ between and、in

连接条件运算

and、or、not

当查询条件有多个时,可能需要同时满足,或者只满足其中一个,或者不满足某个条件,则需要用到或。且。非

null运算nvl()

nul比较特殊需要单独处理
is null、is not null、 not…is null

where子句

判断条件不能直接得到,需要经过计算和过滤的

嵌套查询

1
select * from emp where deptno = (select deptno from dept where dname = 'SALES')

in具体值

1
2
select * from emp where deptno in 'xx'
--查询所有值条件为deptno为xx的具体条目

模糊查询 like

任意个任意字符 % :占用若干字符(添加在字符前面表示可以有若干字符)

一个任意的字符 _ :占用一个字符

当查询的条件为比较模糊时,可以使用模糊查询

1
2
3
4
select * from emp where ename like '%S%' ;

//查询emp表里ename列 含有S的属性
注意:内容区分大小写

联表查询 join

七种JOIN理论

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--inner join

SELECT s.studentno,studentname,subjectno,studentresult
FROM student AS s
INNER JOIN result AS r
ON s.`studentno` =r.`studentno`;

--right join

SELECT s.studentno,studentname,subjectno,studentresult
FROM student s
RIGHT JOIN result r
ON s.`studentno` =r.`studentno`;

--left join

SELECT s.studentno,studentname,subjectno,studentresult
FROM student s
LEFT JOIN result r
ON s.`studentno` =r.`studentno`;

自连接

把一个表分为两个表

**example:**有一个表

对其作分类,父类的categoryid=子类的pid

1
2
3
SELECT f.`categoryname` AS father ,s.`categoryname` AS son
FROM category AS f,category AS s
WHERE f.categoryid = s.pid

排序和分页

order by排序

子查询嵌套查询

mysql函数

函数介绍

OracleSQL提供了用于执行特定操作的专用函数,这些函数大大增强了SQL语言的功能。函数可以接受零个或者多个输入参数,并且返回一个输出结果。这种由Oracle提供给我们的函数我们称为内置函数,除了有内置函数外还可以自定义函数。

​ 根据函数的返回结果,我们将函数分为单行函数和多行函数

1、单行函数:对应在表记录时,一条记录返回一个结果。例如lower(x),将参数转换为小写

2、多行函数:也称组函数或聚合函数(重点):此类函数可同时对多条记录进行操作,并返回一个结果(重点)。例如max(x)求最大值。

常用单行函数

字符串函数

concat(x,y)连接字符串x和y

instr(x,str,start,n).在x中查找str,可以指定从start开始,也可以指定从第n次开始

length(x)返回x的长度

lower(x)x转换为小写

upper(x)x转换为大写

ltrim(xtrim_str)把x左边截去trim_str字符串,缺省截去空格

rtrimt(xtrim_str)把x右边截去trim_str字符串,缺省截去空格

replace(x,old,new)在x中查找old,并替换为new

substr(x,start ,length)返回x的字符串,从start处开始,截取length个字符,缺省length,默认到结尾

数学函数

abs(x) x的绝对值

ceil(x) 向上取整

floor(x) 向下取整

mod(x,y) 对x求y的余数

日期函数

sysdate 当前系统时间

current_date 返回当前系统日期

add_months(d1,n1)返回在日期d1基础上再加n1个月后新的日期

last day(d1)返回日期d1所在月份最后一天的日期

months_between(d1.d2)返回日期d1到日期d2之间的月数

next_day(d1c1)返回日期d1在下周,星期几(参数c1)的日期

转换函数

to_char(x.c)将日期或数据x按照c的格式转换为char数据类型

to_date(x.c)将字符串x按照c的格式转换为日期

to_number(x)将字符串x转化为数字型

聚合函数

组函数同时对多条记录进行操作,并返回一个结果

count() 计数

avg() 平均值

sum() 求和

max() 最大值

min() 最小值

注意:null不参与运算

group by分组

group by分组,将满足条件的记录进一步按照某特性进行分组。提取每组记录中的共性

结构:select…from…where….goup by….

1
select deptno,count(deptno) from emp group by deptno;

having过滤组信息

要获取的组信息也许要满足一定条件时,我们通过hving来过滤组的条件。

结构:select…from…where…group by …having…

过滤行记录和组信息

行记录的过滤是针对每条记录的筛选,组信息的过滤是针对组的筛选,是可以同时出现的,先筛选行,再过滤组。

where筛选行,只能出现行信息

having过滤组,只能出现组信息

结构:select…from…where…groupby…having

2.3伪列和虚表

2.3.1伪列和表达式

说明:查询不存在的列即伪列,当需要的结果不能直接从表中得到需要经过计算来展示则可以使用伪列
+表达式实现

1
2
select 1 from emps
select ename,1 from emp;

查询员工的名称,工种,月工资,以及年薪(年薪=12个月的工资)
查询每个工资等级的平均工资(平均工资=(最低工资+最高工资)/2)

1)null处理 —nvl()

1
select 条件+nvl(列,返回的数值) from 表;

查询员工的名称,工种,工资,奖金,以及月收入(月收入=工资+奖金)

2)字符串拼接||

1
select 列名/条件||'要拼接的字符串' form 表名;

查询员工的员工编号,姓名,以及将员工姓名和工种进行拼接后的字段(员工姓名-工种)

2.3.2虚表dual

​ dual是一个虚表,虚拟表,是用来构成select的语法规则,oracle保证dual里面永远只有一条记录。该表只有一行一列,它和其他表一样,可以执行插入、更新、删除操作,还可以执行drop操作。但是不要去执行drop表的操作,否则会使系统不能用,起不了数据库。

​ dual主要用来选择系统变量或是求一个表达式的值。如果我们不需要从具体的表来取得表中数据,而是单纯地味了得到一些我们想得到的信息,并要通过select完成时,就要借助一个对象,这个对象就是dual。

事务

事务的四大特性

谈到事务一般都是以下四点:

1.原子性(Atomicity)
过去原子被认为是分割的最小单位, 类比事务, 事务是一个不可分割的工作单位, 事务中的操作要么全部成功要么全部失败.

这个过程包含两个步骤:

1.A转给B 200元, A剩余600元

2.B收到A 200元, B剩余400元

原子性表示, 这两个步骤不可分割, 要么全部成功要么全部失败.

2.一致性(Consistency)
事物提交前和提交后, 数据都是合法的一致性状态, 即使发生异常也不会破坏数据库的完整性约束.(符合逻辑运算)

假设要求事务执行前后总有A的账户余额+B的账户余额=1000, 那么事务执行后该完整性约束仍然满足.因此这个事务就满足一致性.

3.隔离性(isolation)
多个用户并发(同时)访问数据库时, 数据库为每一个用户都开启事物, 为了防止多个事物的操作数据相互干扰, 多个并发事物之间要相互隔离.隔离性通过事务的隔离级别来定义, 并用锁机制来保证写操作的隔离性, MVCC来保证读操作的隔离性.

假设A只有500元, 如果没有隔离性, 两个事务同时进行, 事务2可能会读取到事务1还未提交的数据.此时A就会转出700, 这显然是不符合逻辑的, 隔离性就是为了解决上述问题.

4.持久性(durability)
一个事物一旦被提交, 它对数据库的改变就是永久的, 不管是断电还是机器故障也不会对其有任何影响, 通过事务中重做日志(redo log)来保证, 事务修改之前会将变更信息预写到 redo log中, 如果数据库宕机, 恢复后会读取redo log中的数据恢复数据.

隔离会导致的一些问题

手动处理事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
set autocommit = 0	/*关闭自动提交*/
set autocommit = 1 /*开启自动提交*/



--事务的手动处理
set autocommit = 0 /*关闭自动提交*/

start transcation --标记一个事务的开始,之后sql都在同一个事务内
insert xxx
insert xxx

--提交:持久化(succes)
commit
--回滚:回到某个位置(fail)
rollback

--事务结束
set autocommit = 1 /*开启自动提交*/

--了解
savepoint 名称 --设置事务保存点
rollback to savepoint 名称 --回滚到保存点
release savepoint 名称 --撤销保存点

模拟转账场景

索引

分类

  • 主键索引

    • 唯一标识,主键不可重复,只能有一列作为主键
  • 唯一索引

    • 避免重复列出现,唯一索引可以重复,多个列都可以标识为唯一索引
  • 常规索引

    • 默认的,index,key关键字来设置
  • 全文索引

    • 在特定引擎下才有 MyISAM
    • 快速定位数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--索引的使用
--1.在创建表时给字段增加索引
--2.创建完毕后增加索引

--显示所有索引
show index from student
--show index from 表名


--增加一个全文索引(索引名) 列名
alter table school.student add fulltext index `studentname`(`studentname`)

--explain 分析sql执行情况
explain select * from student; --非全文索引

explain select * from student where match(studentname) against('刘');

权限管理和备份

用户管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
--创建用户 
CREATE USER loh IDENTIFIED BY '123456'

--修改当前用户密码
SET PASSWORD = PASSWORD('12345678')
--修改指定用户密码
SET PASSWORD FOR loh@% = PASSWORD('12345678')

--重命名 rename user 旧名字 to 新名字
rename user loh to loh2

--用户授权all privileges全部权限,库,表
--all privileges权限,包含除授权权限外的全部权限
grant all privileges on *.* to loh2

--查询权限
show grants for loh2
show grants for root@localhost

--root用户权限:grant all privileges on *.* 'root'@'localhost' with grant option

--撤销权限, revoke哪些权限在哪个库撤销
revoke all privileges on *.* from loh2

--删除用户
drop user loh2

mysql备份

  • 保证安全性
  • 数据转移

数据库设计

三大范式

第一范式:

原子性,保证不可再分

第二范式:

在第一范式基础上,每张表只描述一件事情

第三范式:

第三范式需要确保数据表的每一列都与主键直接相关,不能间接相关

JDBC(重点)

数据库驱动

下载mysql驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 //加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");

//设置数据库地址,使用unicode编码,使用utf8编码,使用安全连接
String url = "jdbc:mysql://localhost:3306/jdbcstu?useUnicode=true&character=utf8&useSSL=true";
//用户名 密码
String username = "root";
String password = "123456";

//连接并获取数据库对象
Connection connection = DriverManager.getConnection(url,username,password);

//执行sql的对象
Statement statement = connection.createStatement();
//定义sql语句
String sql = "SELECT * FROM USER";
//获取执行sql的结果对象
ResultSet resultSet = statement.executeQuery(sql);

//循环输出
while (resultSet.next()){
System.out.println("id:"+resultSet.getObject("id"));
System.out.println("name:"+resultSet.getObject("name"));
System.out.println("pwd:"+resultSet.getObject("password"));
System.out.println("email:"+resultSet.getObject("email"));
System.out.println("birth:"+resultSet.getObject("birthday"));
}

//释放连接
resultSet.close();
statement.close();
connection.close();

DriverManager

1
2
3
4
5
//加载驱动1
Class.forName("com.mysql.cj.jdbc.Driver");

//加载驱动2
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());

statement执行类

execute执行语句

statement对象

jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。

CRUD操作 – create

使用executeUpdate(String sql)方法完成数据添加操作,示例操作:

1
2
3
4
5
6
Statement st = conn.createStatement();
String sql = "insert into user(...) values(....)";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!");
}

CRUD操作 – delete

使用executeUpdate(String sql)方法完成数据删除操作

1
2
3
4
5
6
Statement st = conn.createStatement();
String sql = "delete from user where id = 1";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("删除成功!");
}

CRUD操作 – update

使用executeUpdate(String sql)方法完成数据修改操作

1
2
3
4
5
6
Statement st = conn.createStatement();
String sql = "update user set name = '' where name = '' ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("修改成功!");
}

CRUD操作 – read

使用executeQuery(String sql)方法完成数据库查询操作

1
2
3
4
5
6
Statement st = conn.createStatement();
String sql = " select * from user where id = 1 ";
int num = st.executeUpdate(sql);
while(rs.next()){
//根据获取列表的数据类型,分别调用rs的相应方法映射到JAVA对象中
}

插入数据程序实例

新建db,properties文件,存放连接数据库所用参数

db.properties文件

1
2
3
4
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
username= root
password = root

新建工具类,写有连接数据库使用的代码,方便其他类调用。

jdbcUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.wang.liesson2.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class jdbcUtils {

private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;

static{
try{
InputStream in = jdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//驱动只需要加载一次
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}

//获取连接
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,username,password);
}

//释放连接资源
public static void release(Connection conn, Statement st, ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

测试插入类

TestInsert.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.wang.liesson2;

import com.wang.liesson2.utils.jdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestInsert {
public static void main(String[] args)
{
Connection conn = null;
Statement st = null;
ResultSet rs = null;

try {
conn = jdbcUtils.getConnection(); //获取连接
st = conn.createStatement(); //创建Statement对象

String sql = "INSERT INTO users (id,`NAME`,`PASSWORD`,`email`,`birthday`)\n" +
"VALUES(4,'wangchen','123456','3247829@qq.com','2021-1-1')\n";

int i = st.executeUpdate(sql);
if(i>0){ //如果数据大于0
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.release(conn,st,rs);
}
}
}

sql注入

sql注入:通过漏洞方法使数据库判断条件为true,未经过过滤直接返回表值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.loh.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class TestSqlInject {
public static void main(String[] args) {
login("' or' 1=1","123456");
}
public static void login(String username,String password){
Connection conn = null;
Statement st = null;
ResultSet rs = null;

try{

conn = JdbcUtils.getConnection();
st=conn.createStatement();

//SELECT * FROM USER WHERE `name` = 'zhangsan' AND `password` = '123456';
String sql = "SELECT * FROM USER where `name` ='"+username+"'and `password` = '"+password+"'";
rs = st.executeQuery(sql);

while (rs.next()){
System.out.println("name:"+rs.getObject("name"));
System.out.println("pwd:"+rs.getObject("password"));
System.out.println("====================");
}

}catch (Exception e){}



}
}

Preparedstatement对象

selcet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.loh.utils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;


public class TestPreparedStatementSelect {
public static void main(String[] args) {
login();
}
public static void login () {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;

try {

conn = JdbcUtils.getConnection();
//使用?作为占位符代替参数预编译
String sql = "select * from user where id = ?";
st = conn.prepareStatement(sql);
//手动给参数赋值
//set可以指定参数类型,(sql参数下标,设置值)
st.setInt(1, 8);

rs = st.executeQuery();
while (rs.next()){
System.out.println("id:"+rs.getObject("id"));
System.out.println("name:"+rs.getObject("name"));
System.out.println("pwd:"+rs.getObject("password"));
System.out.println("email:"+rs.getObject("email"));
System.out.println("birth:"+rs.getObject("birthday"));
}

} catch (Exception e) {

} finally {
JdbcUtils.release(conn, st, null);
}
}
}

insert

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.loh.utils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestPreparedStatementInsert {
public static void main(String[] args) {
login();
}
public static void login(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;

try{

conn = JdbcUtils.getConnection();
//使用?作为占位符代替参数预编译
String sql = "insert into user(`id`,`name`,`password`,`email`,`birthday`) values(?,?,?,?,?)";
st=conn.prepareStatement(sql);
//手动给参数赋值
//set可以指定参数类型,(sql参数下标,设置值)
st.setInt(1,9);
st.setString(2,"wangwu");
st.setString(3,"654321");
st.setString(4,"654321@da.com");
st.setDate(5,new java.sql.Date(new java.util.Date().getTime()));
int i = st.executeUpdate();

if(i > 0 ){
System.out.println("插入成功");
}


}catch (Exception e){

}finally {
JdbcUtils.release(conn,st,null);
}
}
}

IDEA连接数据库

img

  • 找到database
  • 点击“+”
  • 点击Data Source
  • 最后点击Mysql

配置连接💎

img

  • 连接的名称
  • 连接数据库的地址跟端口 地址默认localhost 端口默认3306
  • 数据库的用户名跟密码
  • 需要连接数据库的名字
  • 测试连接

接着就是配置我们的驱动!

img

Drivers->MySQL->Driver files

回到 Date Sources,出现***绿色的小勾***,即表示连接成功,然后点击OK,结束配置。

img

还有一种情况

img

相信大家都会遇到这种情况吧

小王来教大家如何解决!

我们先把错误代码copy 翻译一下

img

这就是mysql里的时区是默认的!

我们需要更改时区!

show variables like’%time_zone’;

注意***分号不能省略***

img

默认是system

我们需要插入一条sql语句

  • set time_zone=’+8:00’;

img

接着小王才查看一下!

img

成功!!

img

接下来点击Database

默认是system

我们需要插入一条sql语句

  • set time_zone=’+8:00’;

img

接着小王才查看一下!

img

成功!!

img

接下来点默认是system

我们需要插入一条sql语句

  • set time_zone=’+8:00’;

img

接着小王才查看一下!

img

成功!!

img

接下来点击Database

默认是system

我们需要插入一条sql语句

  • set time_zone=’+8:00’;

img

接着小王才查看一下!

img

成功!!

img

接下来点击Database

img

IDEA操作事务

  • 关闭自动提交

  • 提交事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.loh.utils;

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 user set `id` = '15' where id = '10'" ;
st=conn.prepareStatement(sql1);
String sql2 = "update user set `id` = '16' where id = '8'" ;
st=conn.prepareStatement(sql2);

int i=st.executeUpdate();

//业务完成,提交事务
conn.commit();

if(i > 0 ){
System.out.println("修改成功");
}

}catch (SQLException e){
try {
conn.rollback();
}catch (SQLException e1){
e1.printStackTrace();
}
}finally {
JdbcUtils.release(conn,st,null);
}
}

}

数据库连接池

DBCP

C3P0


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!