mysql
{内容}——{}括号内的为必填
[内容]——[]括号内的为选填
操作数据库
操作数据库的语句(扩展版)
创建数据库
CREATE DATABASE [IF NOT EXISTS] {base_name}
删除数据库
DROP DATABASE [IF EXISTS] {base_name}
使用数据库
USE {base_name}
-- 如果base_name是mysql的关键词可以通过加``包裹来使用 例如 USE {`base_name`}
查看数据库
SHOW DATABASE -- 查看所有数据库
查看创建数据库的语句
SHOW CREATE DATABASE {base_name} -- 查看创建数据库时所使用的sql语句
查看数据库表的定义语句
SHOW CREATE TABLE {table_name} -- 查看数据库表的定义语句
显示表的结构
DESC {table_name}
创建表
-- 字段属性修饰词多个之间用空格分隔
-- 字段之间用英文逗号,分隔最后一个字段可以不加
-- 表名与字段名尽量用''包裹,理由是不知道写的名字什么时候就突然变成高亮关键字影响可读性
CREATE TABLE [IF NOT EXISTS] {`table_name`} (
{`字段名`} {字段的数据类型} [字段的属性修饰词可以多个] [索引] [注释],
{`字段名`} {字段的数据类型} [字段的属性修饰词可以多个] [索引] [注释],
[其他字段]
)[表类型][字符集][注释]
-- [表类型][字符集]
-- ENGINE=INNODB DEFAULT CHARSET=utf8
修改表
-- 修改表名
ALTER TABLE {原表名} RENAME AS {新表名}
-- 增加表的字段
ALTER TABLE {表名} ADD {字段定义语句}
-- 修改表的字段(重命名,修改约束)
ALTER TABLE {表名} CHANGE {原字段名} {新字段名} [新约束]
-- 修改表的字段(修改约束)
ALTER TABLE {表名} MODIFY {字段名} {新约束}
-- 删除表的指定字段
ALTER TABLE {表名} DROP {字段名}
删除表
-- 删除表
DROP TABLE [IF EXISTS] {表名}
数据库的列类型
数值
整数
| 关键词 | 描述 | 大小 | 常见用途 |
|---|---|---|---|
| tinyint | 十分小的数据 | 1字节 | |
| smallint | 较小的数据 | 2字节 | |
| mediumint | 中等的数据 | 3字节 | |
| int | 标准的整数 | 4字节 | 日常 |
| bigint | 较大的数据 | 8字节 |
浮点数
| 关键词 | 描述 | 大小 | 常见用途 |
|---|---|---|---|
| float | 单精度浮点数 | 4字节 | |
| double | 双精度浮点数 | 8字节 | 日常 |
| decimal | 字符串形式的浮点数 | 金融 |
字符串
| 关键词 | 描述 | 大小 | 常见用途 |
|---|---|---|---|
| char | 固定大小的字符串 | 0~255 | |
| varchar | 可变大小的字符串 | 0~65535 | 日常 |
| tinytext | 微型文本 | 2^8-1 | 博客 |
| text | 文本串 | 2^16-1 | 大型书籍 |
时间日期
java.util.Date
| 关键词 | 描述 | 大小 | 常见用途 |
|---|---|---|---|
| date | YYYY-MM-DD,日期格式 | ||
| time | HH: mm: ss,时间格式 | ||
| datetime | YYYY-MM-DD HH: mm: ss | 日常 | |
| timestamp | 时间戳,1970.1.1到现在的毫秒数 | 日常 | |
| year | 年份表示 |
null
- 没有值,未知,空
- ==注意,不要使用NULL进行运算,结果一定为NULL==
数据库的字段属性(重点)
Unsigned
- 无符号的整数
- 声明了该列不能为负数
zerofill
- 0填充的
- 不足的位数会使用0来填充,int(3),5 ... 005
自增
-- 自增
AUTO_INCREMENT
- 通常理解为自增,自动再上一条记录的基础上+1(默认)
- 通常用来设计唯一的主键~ index,必须是整数类型
- 可以自定义主键自增的起始值和步长
非空 NUII not null
-- 非空
NOT NULL
- 非空
- 假设设置为 not null,如果不给它赋值就会报错
- NUII,如果不填写值,默认为null
默认
-- 默认
DEFAULT {默认内容}
- 设置默认的值
- 如果该列不填写值,则会写入设置好的默认值
注释
-- 注释
COMMENT '{内容}'
主键
-- 主键 修饰词写法
PRIMARY KEY
-- 主键 建表中单句声明写法
PRIMARY KEY ({字段名})
数据表的类型
数据库引擎
ENGINE={数据库引擎}
| INNODB | MYISAM | |
|---|---|---|
| 事务支持 | 支持 | 不支持 |
| 数据行锁定 | 支持 | 不支持 |
| 外键约束 | 支持 | 不支持 |
| 全文索引 | 不支持 | 支持 |
| 表空间的大小 | 较大,约为较小的2倍 | 较小 |
INNODB
默认使用
- 安全性高
- 事务的处理
- 多表多用户操作
MYISAM
早些年使用的
- 节约空间
- 速度较快
- 新版支持事务
数据库字符集编码
mysql默认字符集编码Latin1
-- 建表时设置字符集编码
CHARSET={字符集编码}
-- 如utf8
#在my.ini中配置默认的字符集编码
character-set-server=utf8
拓展
注意事项
数据库的数据类型长度问题
int
int(x)
其中x与数据实际长度无关
x为数据显示长度
影响0填充效果
varchar与char
varchar(x)
其中x为实际字符最长长度
项目规范
每个表必须存在的字段
做项目用的,表示一个记录存在的意义
id——主键
version——乐观锁
is_delete——伪删除
gmt_create——创建时间
gmt_update——修改时间
MySQL数据管理
外键(物理外键)
不建议使用(避免数据库过多时造成困扰)
数据库级别的外键(物理外键)
最好数据库只用来存数据,最好只有行(数据)和列(字段)
想使用多张表的数据,想使用外键时去程序层面去实现
删除有被外键引用的表时必须先删除引用外键的表
创建表时添加外键约束
-- 定义外键key
KEY {`key_name`} ({`字段名`})
-- 通常外键key用`FK_字段名`命名
-- 给外键key添加约束(执行引用)
CONSTRAINT {`key_name`} FOREIGN KEY ({`字段名`}) REFERENCES {外表名}({`外字段名`})
给已存在的表添加外键约束
-- 选择修改表
ALTER TABLE {`table_name`}
-- 添加外键引用约束
ADD CONSTRAINT {`key_name`} FOREIGN KEY ({`字段名`}) REFERENCES {外表名}({`外字段名`})
DML语言
数据库的意义:数据存储,数据管理
DML语言:数据库操作语言
- insert
- update
- delete
添加
-- 插入语句(添加)
INSERT INTO {table_name}([字段1,字段2,字段组]) VALUES([值1,值2,值组])
-- 值需要与字段对应
-- 插入多条数据语句(添加)
INSERT INTO {table_name}([字段]) VALUES([第1条数据的值]),([第n条数据的值])
-- 插入语句(添加)(省略字段版)
INSERT INTO {table_name} VALUES([所有字段分别对应的值])
-- 需要将所有字段按顺序对应的值依次全部声明
- 字段和字段之间使用英文逗号
,隔开 - 但如果省略字段,后面的值必须与所有字段一一对应不能少
- 可以同时插入多条数据,使用英文逗号
,隔开
修改
-- 语法
UPDATE 表名 SET colnum_name = value [,colnum_name = value......] WHERE [条件]
colnum_name是数据库的列,尽量带上``- 条件,筛选的条件,如果没有指定,则会修改所有的列
value是一个具体的值,也可以是一个变量- 多个设置的列之间用英文逗号
,隔开
基本语句
-- 修改表内指定数据的值
UPDATE {table_name} SET {改动} WHERE {条件}
-- 修改表内多个指定数据的值
UPDATE {table_name} SET {改动1,改动2,改动n} WHERE {条件}
-- 修改表内全部数据的值
UPDATE {table_name} SET {改动}
-- 改动
{字段名}={修改后的值}
-- 条件语句
操作符
| 操作符 | 含义 | 范围 | 结果 | ||
|---|---|---|---|---|---|
= | 等于 | 5=6 | false | ||
<>或!= | 不等于 | 5<>6 | true | ||
> | 大于 | ||||
< | 小于 | ||||
>= | 大于等于 | ||||
<= | 小于等于 | ||||
BETWEEN…AND… | 在…与…之间 | 闭合区间 | |||
AND | 与&& | 用于连接条件语句 | |||
OR | 或` | ` | 用于连接条件语句 | ||
删除
DELETE与TRUNCATE的区别
- 相同点:
- 都能删除数据
- 都不会删除表结构
- 不同点:
TRUNCATE会重新设置自增列,计数器会归零TRUNCATE不会影响事务
删除
DELETE FROM {表名}
DELETE FROM {表名} WHERE {条件}
DELETE删除的问题,重启数据库,现象
- INNODB 自增列会从1开始(存在内存当中的,断电即失)
- MYISAM 继续从上一个自增量开始(存在文件中的,不会丢失)
清空
TRUNCATE {表名}
TRUNCATE TABLE {表名}
DQL查询数据(重点)
DQL
Data Query Language 数据查询语句
- 所有查询操作都用它 Select
- 简单的查询,复杂的查询它都能做
- 数据库中最核心的语言,最重要的语句
- 使用频率最高的语句
指定查询字段
语法
-- 语法
SELECT 字段...... FROM 表
- 当在查询出的列名或表名不能见名知意时可以使用起别名
AS关键字解决- 字段名
AS别名 - 表名
AS别名
- 字段名
SELECT完整语法
SELECT [ALL | DISTINCT] -- 查全部或者去重,默认查全部
{* | table.* | [table.field1[AS alias1]][,table.field2[AS alias2]][......]} -- 显示列
FROM {table_name [AS table_alias]} -- 查询的表
[{ LEFT | RIGHT | INNER } JOIN table_name2 ON ...] -- 联表查询
[WHERE ...] -- 指定结果需要满足的条件
[GROUP BY ...] -- 指定结果按照几个字段来分组
[HAVING ...] -- 过滤分组的记录必须满足的次要条件
[ORDER BY ...] -- 指定查询记录按一个或多个条件排序
[LIMIT {[ offset,]row_count | row_countOFFSET offset}]; -- 指定查询的记录从哪条到哪条
基本查询
-- 查询表内全部字段
SELECT * FROM {表名}
-- *是通配符
-- 查询表内指定字段
SELECT {字段集} FROM {表名}
-- 字段集中的字段有多个时用英文逗号,分割
-- 给查出的字段起别名
SELECT {字段名} AS {别名} FROM {表名}
-- 多个字段时也是用用英文逗号,分割
-- 现在可以省略AS用空格分隔
-- 函数 Concat(a,b) 字符串拼接
SELECT CONCAT({添加的},{字段名}) AS {别名}
FROM {表名}
-- 给字段的所有指定数据添加拼接字符串,只用于查询结果显示,不影响真实库内数据
去重
-- 指定字段 数据去重
SELECT DISTINCT {字段名} FROM {表名}
数据库的列(表达式)
语法
-- 语法
SELECT 表达式 FROM 表
数据库中的表达式
- 文本值
- 列
- NULL
- 函数
- 计算表达式
- 系统变量
- ……
用法
-- 查询系统版本(函数)
SELECT VERSION()
-- 查计算结果(表达式)
SELECT {计算表达式} [AS 别名]
-- 如1+1*1
-- 查询自增的步长(变量)
SELECT @@auto_increment_increment
-- 统一加1显示查询,不更改原数据
SELECT {字段名}+1 [AS 别名] FROM {表名}
WHERE条件子句
检索数据中 符合条件 的值
搜索的条件由一个或者多个表达式组成,结果一般为布尔值
等值查询
操作符
逻辑运算符
| 运算符 | 语法 | 描述 | ||
|---|---|---|---|---|
AND && | a AND b a && b | 逻辑与 | ||
OR ` | ` | a OR b a || b | 逻辑或 | |
NOT ! | NOT a !a | 逻辑非 |
- 尽量使用英文字母
比较操作符:模糊查询
| 运算符 | 语法 | 描述 |
|---|---|---|
IS NULL | a IS NULL | 如果a为NULL则结果为真 |
IS NOT NULL | a IS NOT NULL | 如果a不为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在在其中一个值中则结果为真 |
-
LIKE搭配的通配符%代表任意个字符,包括零个_代表一个字符
-
IN需要具体的一个或多个值
联表查询
跨表连接
JOIN...ON... 连接查询
{连接关键词} JOIN {连接的表} ON {判断的条件}
-- INNER JOIN 交集查询
SELECT {[表别名.]字段名} FROM {左表名} [AS 别名] INNER JOIN {右表名} [AS 别名] ON {表别名.字段名} = {表别名.字段名}
-- ON后面是两张表相关联的条件
-- LEFT JOIN 左查询(左表为主显示表)
SELECT {[表别名.]字段名} FROM {左表名} [AS 别名] LEFT JOIN {右表名} [AS 别名] ON {表别名.字段名} = {表别名.字段名}
-- ON后面是两张表相关联的条件
-- RIGHT JOIN 右查询(右表为主显示表)
SELECT {[表别名.]字段名} FROM {左表名} [AS 别名] RIGHT JOIN {右表名} [AS 别名] ON {表别名.字段名} = {表别名.字段名}
-- ON后面是两张表相关联的条件
| 操作 | 描述 |
|---|---|
INNER JOIN | 会从两表交集中返回所有的值 |
LEFT JOIN | 会从左表中返回所有的值,即使右表中没有匹配 |
RIGHT JOIN | 会从右表中返回所有的值,即使左表中没有匹配 |
自连接
-- 自连接查询
SELECT {[表别名.]字段名} , {[表别名.]字段名} FROM {表名} [AS 别名] , {表名} [AS 别名] WHERE {连接关系等式}
分页和排序
排序
升序
ORDER BY {字段名} ASC
降序
ORDER BY {字段名} DESC
分页
LIMIT {起始值},{页面大小}
- 缓解数据库压力,给人的体验更好
子查询
SELECT {字段名} FROM {表名} WHERE 字段名 = (SELECT {字段名} FROM {表名} WHERE {关系式})
-- 括号内为子查询
- 在
WHERE中嵌套查询语句 - 可多嵌套
分组和过滤
[GROUP BY ...] -- 指定结果按照几个字段来分组
[HAVING] -- 过滤分组的记录必须满足的次要条件
- 分组时不能使用
WHERE
MySQL函数
常用函数
数学函数
-- 绝对值
SELECT ABS({数字})
-- 向上取整
SELECT CELLING({数字})
-- 向下取整
SELECT FLOOR({数字})
-- 随机数(0~1)
SELECT RAND()
-- 返回数字的符号(0:0;负数:-1;正数:1;)
SELECT SIGN({数字})
字符串函数
-- 字符串长度
SELECT CHAR_LENGTH('123')
-- 拼接字符串
SELECT CONCAT('1','2','3')
-- 插入,从某个位置开始插入替换某个长度(本体,位置,长度,替换值)
SELECT INSERT('1245',2,1,'23')
-- 转为小写字母
SELECT LOWER('Ab')
-- 转为大写字母
SELECT UPPER('Ab')
-- 返回第一次出现子串的索引
SELECT INSTR('1212','2')
-- 替换出现的指定字符串
SELECT REPLACE('124','4','3')
-- 返回指定位置与长度的字符串
SELECT SUBSTR({本体},{位置}[,长度])
-- 反转
SELECT REVERSE('123')
时间和日期函数
-- 获取当前日期
SELECT CURRENT_DATE()
SELECT CURDATE()
-- 获取当前的时间
SELECT NOW()
-- 本地时间
SELECT LOCALTIME()
-- 系统时间
SELECT SYSDATE()
-- 年
SELECT YEAR({时间})
-- 月
SELECT MONTH({时间})
-- 日
SELECT DAY({时间})
-- 时
SELECT HOUR({时间})
-- 分
SELECT MINUTE({时间})
-- 秒
SELECT SECOND({时间})
系统
-- 当前用户
SELECT SYSTEM_USER()
SELECT USER()
-- 当前版本
SELECT VERSION()
聚合函数
| 函数名称 | 描述 |
|---|---|
COUNT() | 计数 |
SUM() | 求和 |
AVG() | 平均值 |
MAX() | 最大值 |
MIN() | 最小值 |
| ... | ... |
COUNT()情况COUNT(字段)会忽略所有null值COUNT(*)统计所有列COUNT(1)所有列变为1后统计所有列
数据库级别的MD5加密
MD5({值})
- MD5不可逆
- MD5可碰撞
- MD5破解是字典暴力破解
事务
要么都成功,要么都失败
将一组SQL放在一个批次中执行
事务原则 ACID原则
原子性,一致性,隔离性,持久性
(脏读,不可重复读,幻读……)
原子性(Atomicity)
针对同一个事务的
要么都成功,要么都失败
一致性(Consistency)
事务操作前后的数据完整性要保证一致
隔离性(Isolation)
两个用户同时操作时要互相隔离
持久性(Durability)
事务结束后的数据不随着外界原因导致数据丢失
事务没提交就恢复原状
事务提交了就持久化到数据文件了
事务一但提交就不可逆
事务的隔离级问题
脏读
指一个事务读取了另一个事务未提交的数据
不可重复读
在一个事务内读取表中的某一行数据,多次读取结果不同(不一定是错误,只是某些场合不对)
虚读(幻读)
指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致
MySQL事务
-- MySQL事务自动提交
SET autocommit = 1 -- 开启(默认)
SET autocommit = 0 -- 关闭
-- 事务开启
START TRANSACTION -- 标记一个事务的开始
-- 提交:持久化(成功)
COMMIT
-- 回滚:回到原来的样子(失败)
ROLLBACK
-- 设置一个事务的保存点
SAVEPOINT {保存点名}
-- 回滚到一个事务保存点
ROLLBACK TO SAVEPOINT {保存点名}
-- 撤销指定保存点
RELEASE SAVEPOINT {保存点名}
手动处理流程
-- 手动处理事务
SET autocommit = 0 -- 关闭自动提交
-- 事务开启
START TRANSACTION -- 标记一个事务的开始
-- 提交:持久化(成功)
COMMIT
-- 回滚:回到原来的样子(失败)
ROLLBACK
-- 事务结束
SET autocommit = 1 -- 开启自动提交
索引
索引(Index)是帮助MySQL高效获取数据的数据结构,提取句子主干,就可以得到索引的本质,索引是数据结构
索引的分类
在一个表中,主键索引只能有一个,唯一索引可以有多个
主键索引PRIMARY KEY
唯一的标识,主键不可重复,只能由一个列作为主键
唯一索引UNIQUE KEY
避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引
常规索引KEY或INDEX
默认的,用KEY或INDEX关键字来设置
全文索引FULLTEXT
在特定的数据库引擎下才能使用
快速定位数据
索引的使用
- 在创建表的时候给字段添加索引
- 创建完毕后,增加索引
-- 显示所有索引信息
SHOW INDEX FROM {表名}
-- 增加一个全文索引
ALTER TABLE 库名.表名 ADD FULLTEXT INDEX 索引名(字段名)
-- EXPLAIN 分析sql执行的状况
EXPLAIN SELECT * FROM 表名 -- 非全文索引
EXPLAIN SELECT * FROM 表名 WHERE MATCH({不知道是字段还是索引名}) AGAINST({要查的东西}) -- 我心情不好去他娘的我也不知到说的啥
-- 给指定字段添加索引
CREATE INDEX 索引名 ON 表名(字段名)
-- 常规索引命名规范:id_表名_字段名
索引原则
- 索引不是越多越好
- 不要对经常变动的数据加索引
- 小数据量的表不需要加索引
- 索引一般加在常用来查询的字段上
索引的数据结构
Hash类型的索引
Btree:InnoDB的默认数据结构
详细的请自行百度
权限管理与备份
用户管理
SQL yog 可视化管理
- 没什么好说的,略过
SQL命令操作
用户表:mysql.user
本质:对这用户表进行增删改查
-- 创建用户
CREATE USER 用户名 [ IDENTIFIED BY 密码]
-- 修改用户密码(当前用户)
SET PASSWORD = PASSWORD('密码')
-- mysql8版本不一定能用,可能被取消了
-- 修改用户密码(指定用户)
SET PASSWORD FOR 用户名 = PASSWORD('密码')
-- 重命名
RENAME USER 前用户名 TO 改后用户名
-- 指定用户授权(所有权限,无授权权限)
GRANT ALL PRIVILEGES ON 库名.表名 TO 用户名
-- 库名.表名 可以用 *.* 实现所有
-- ALL PRIVILEGES 的所有权限中不包括给用户授权的权限,无法给其他用户授权
-- 指定用户授权(所有权限,有授权权限)
GRANT ALL PRIVILEGES ON 库名.表名 TO 用户名@主机 WITH GRANT OPTION
-- ROOT用户权限:GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
-- 查询指定用户的权限
SHOW GRANTS FOR 用户名
-- 查管理员的时候需要在名字后面加上@主机(如 root@localhost)
-- 撤销权限(所有权限,授权权限没了解)
REVOKE ALL PRIVILEGES ON *.* FROM 用户名
-- 删除用户
DROP USER 用户名
MySQL备份
- 保证重要的数据不丢失
- 数据转移
MySQL数据库备份的方式
-
直接拷贝物理文件
-
在sqlyog这种可视化工具中手动导出
-
使用
命令行导出:mysqldump
命令行方式
导出
# mysqldump -h 主机 -u 用户名 -p 密码 数据库名 表名 >物理磁盘位置/文件名.sql
mysqldump -h localhost -u root -p 123456 school student >D:/a.sql
# 多张表
# mysqldump -h 主机 -u 用户名 -p 密码 数据库名 表名1 表名2 表名3 >物理磁盘位置/文件名.sql
# 导出数据库级
# mysqldump -h 主机 -u 用户名 -p 密码 数据库名 >物理磁盘位置/文件名.sql
导入
#(需要从命令行登录mysql后)
# 导入数据库级可以直接导入,导入数据表级时需要切换到指定的数据库再导入
# source 物理磁盘位置/文件名.sql
source D:/a.sql
# 命令行可直接执行的导入
# mysql -u 用户名 -p 密码 库名 < 备份文件
规范数据库设计
需要设计的原因
当数据库比较复杂的时候,我们就需要设计了
糟糕的数据库设计:
- 数据沉余
- 数据库插入和删除都会麻烦、异常【屏蔽使用物理外键】
- 程序的性能差
良好的数据库设计:
- 节省内存空间
- 保证数据库的完整性
- 方便我们开发系统
软件开发中,关于数据库的设计
- 分析需求:分析业务和需要处理的数据库需求
- 概要设计:设计关系图 E-R图
设计数据库的步骤(个人博客)
- 收集信息,分析需求
- 用户表(用户登录注销,用户的个人信息,写博客,创建分类)
- 分类表(文章分类,谁创建的)
- 文章表(文章的信息)
- 评论表
- 友链表(友链信息)
- 自定义表(系统信息,某个关键字,或者一些主字段) key:value【非规范】
- 说说表(发表心情
idcontentcreate_time)
- 标识实体(把需求落地到每个字段)
- 标识实体 之间的关系
- 写博客:user —》 blog
- 创建分类:user —》 category
- 关注:user —》 user
- 友链:links
- 评论:user—user—blog
三大范式
解决的问题
- 信息重复
- 更新异常
- 插入异常
- 无法正常显示信息
- 删除异常
- 丢失有效的信息
三大范式
第一范式(1NF)
- 要求数据库表的每一列都是不可分割的原子数据项(原子性)
第二范式(2NF)
- 前提:满足第一范式
- 确保数据库表中的每一列都和主键相关,不能只与主键的某一部分相关(主要针对联合主键)
- 每张表只描述一件事情
- (在1NF基础上消除非主属性对主码的部分函数依赖)
第三范式(3NF)
- 前提:满足第一范式,满足第二范式
- 确保数据表中的每一列数据都和主键直接相关,不能间接相关
- (在2NF基础上消除传递依赖)
规范性 和 性能的问题
关联查询的表不得超过三张表
- 考虑商业化的需求和目标,数据库的性能更加重要(成本,用户体验)
- 在规范性能的问题的时候,需要适当的考虑一下规范性
- 故意给某些表增加一些沉余的字段(从多表查询变为单表查询)
- 故意增加一些计算列(从大数据量降低为小数据量的查询:索引)
其他范式(扩展)
巴斯-科德范式(BCNF)
第四范式(4NF)
第五范式(5NF)
JDBC
数据库驱动
应用程序通过数据库驱动操作数据库
不同的数据库有不同的驱动
规范:JDBC
- SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范,俗称JDBC
- 这些规范的实现由具体的数据库厂商去做
- 对于开发人员来说,我们只需要掌握
JDBC接口即可
java.sql
javax.sql
还要导入一个数据库驱动包,mysql-connector-java-5.1.47.jar
JDBC的java代码应用
import java.sql.*;
public class JdvcFirstDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
class.forName("com.mysql.jdbc.Driver");//固定写法,反射加载驱动
//2.用户信息和url
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username = "root";
String password = "123456";
//3.连接成功,获得数据库对象 Connection
Connection connection = DriverManager.getConnection(url,username,password);
//4.获得执行SQL的对象 Statement
Statement statement = connction.createStatement();
//5.用执行SQL的对象去执行SQL
String sql = "sql语句"
ResultSet resultSet = statement.executeQuery(sql);
//5.5.可能存在结果,查看返回结果
//......
//6.释放连接
resultSet.close();
statement.close();
connection.close();
}
}
DriverManager
//加载驱动
class.forName("com.mysql.jdbc.Driver");//固定写法,反射加载驱动
// DriverManager.registerDriver(new com.mysql.jdbc.Driver());//在源码层面多注册了一次,不建议使用
// connection 代表数据库
// 数据库设置自动提交
// 事务提交
// 事务回滚
connection.rollback();
connection.commit();
connection.srtAutoCommit();
URL
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
// mysql -- 3306
// 协议://主机地址:端口号/数据库名?参数1&参数2&参数3
Statement 执行SQL的对象
String sql = "编写的sql语句";// 编写的sql
statement.executeQuery(sql);//用于查询语句,查询操作返回 ResultSet对象
statement.executeUpdate(sql);//更新、插入、删除。都用这个,返回一个受影响的行数
statement.execute(sql);//执行任何sql
- 存在sql注入问题
SQL注入
通过字符串拼接欺骗服务器的技巧
具体查百度
PrepareStatement 执行SQL的对象
Connention conn = null;
PreparedStatement st = null;
conn = JdbcUtils.getConnection();
//编写sql使用 ?占位符 替代参数
String sql = "编写sql,?,?";
//预编译sql
st = conn.prepareStatement(sql);//并没有执行sql
//手动给参数赋值(键,值)
st.setInt(1,1);//设置整型参数
st.setString(2,"第二个参数");//设置字符串参数
//执行sql
st.executeUpdate();
- 可以防止sql注入
- 效率高
- 使用
?占位符替代实际参数
防sql注入的原理
通过把参数整体转为字符串,并将其中的特殊功能字符自动转义使其失去特殊功能
ResultSet
查询的结果集:封装了所有的查询结果
获得指定数据类型的数据
resultSet.getObject();//在不知道列类型的情况下使用
//如果知道列的类型就使用指定的数据类型
resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
resultSet.getObject();
......
遍历
//光标
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后面
resultSet.next();//移动到下一行
resultSet.previ();//移动到上一行
resultSet.next();//移动到指定行
释放资源
//释放连接 //先关小的,后关大的
resultSet.close();
statement.close();
connection.close();//耗资源,用完关掉
事务相关代码
//数据库的自动提交 关闭后会自动开启事务
connection.setAutoCommit(false);//关闭
//事务回滚 显示定义
connection.rollback();
//提交事务 业务完毕
connection.commit();
- 开启事务后如果失败会自动回滚,也可以在catch语句中显示定义
数据库连接池
池化技术:准备一些预先的资源,过来就连接预先准备好的
最小连接数
最大连接数
等待超时
- 核心:编写连接池,实现一个接口 DataSource
开源数据源实现
使用了这些数据库连接池之后在项目开发中就不需要再编写连接数据库的代码了
- 导jar包
- 写配置文件
- 使用
DBCP
需要用到的jar包
- commons-dbcp-1.4
- commons-pool-1.6
配置文件百度
使用方式百度
C3P0
需要用到的jar包
- c3p0-0.9.5.5
- mchange-commons-java-0.2.19
配置文件百度
使用方式百度