学习网站:https://www.bilibili.com/video/BV1NJ411J79W?from=search&seid=1914316698934444374&spm_id_from=333.337.0.0
简称:DB(DataBase)
概念:数据仓库,软件,安装在操作系统上(window,linux,mac),主要是学SQL,可以存储大量的数据。
作用:存储数据、管理数据
所有的数据库文件都存在data目录下,一个文件夹对应一个数据库
本质上还是文件的存储
关系型数据库:(SQL)
- MySQL、Oracle、SQL、DB2、SQLlite
- 通过表与表之间、行与列之间的关系进行数据的存储,
非关系型数据库:(NoSQL-----不仅仅是SQL)
- Redis、MongDB
- 通过对象存储,通过对象的自身属性决定
- 数据库的管理软件、科学有效的管理、维护、获取数据
- 关系型数据库管理系统、
- 最好的RDBMS应用软件之一
- 开源的数据库软件
- 体积小、速度快,成本低
关闭:
net stop mysql(这个是你的服务名)
开启
net start mysql(同上)
服务名查询:
- 右击此电脑
- 管理
- 服务与应用程序
- 服务
- 找到mysql(或者是其他的,一般都是mysql+....)
mysql -u root -p(密码) ————cmd连接数据库 update mysql.user set authentication_string=password('密码') where user='root' and Host = 'localhost'; ————修改用户密码 ———————————————————————————————————————————————— 1. 在cmd中,使用数据库的所有语句必须使用";"结尾 2. show databases; ————查看所有数据库 3. 输入: user school ————切换数据库 user 数据库名 下一行跳出: Database changed 4. show tables; ————查看数据库所有表 5. describe *****(表的名字)————显示数据库中表的所有信息 6. cerate database ****(数据库的名字)————创建一个数据库 7. exit; ————退出连接 8. "--" 单行注释 9. "/**/" 多行注释
**mysql关键字不区分大小写 **
创建数据库
CREATE DATABASE [IF NOT EXISTS] ***(库名) []内的是可选的删除数据库
DROP DATABASE [IF EXISTS] ****(库名)使用数据库
-- "`",tab键的上面,如果表明或者字段名是一个特殊字符,需要带"`" USER `***(库名)`查看数据库
SHOW DATABASES 查看所有的数据库
数值:
- tinyint ————十分小的数据,占一个字节
- smallint ————较小的数据,占2个字节
- mediumint ————中等大小的数据,占3个字节
- int ————标准整数,4个字节
- big ————较大的数据,占8个字节
- float ————浮点数,占4个字节
- double ————浮点数,占8个字节
- decimal ————字符串形式的浮点数,金融计算是常用
字符串:
- char ————字符串固定大小(0-255)
- varchar ————可变字符串(0-65535),常用的变量 string
- tinytext ————微型文本,2^8-1
- text ————文本串,2^16-1,保存大文本
时间日期:
- date ————YYYY-MM--DD,日期格式
- time ————HH:mm:ss,时间格式
- date ————YYYY-MM-DD-HH:mm:ss,最常用的时间格式
- timestamp ————时间戳,1970.1.1到现在的毫秒数!(全球统一),较为常用
- year ——年
null:
- 没有值,未知的
- ==注意,不要使用NULL进行运算,否则结果一定为NULL
- 无符号的证书
- 声明了该列不能声明为负数
- 0填充
- 不足的位数使用0填充,int(3[此处表示长度]), 5——>005
- 通常理解为自增,自动在上一条记录的基础上加1(默认)
- 通常用来设计唯一的主键---index,必须是整数类型
- 可以自定义涉及主键自增的起始值和步长
- 假设设置为not null,如果不给它赋值,会报错
- NUll,如果不填写,默认是null
- 设置默认值
- 例如:sex,默认为男,如果不指定该列的值,则会有默认的值
- id-----主键
- ”
version
“ --------乐观锁- is_delect-------伪删除
- gmt_create------创建时间
- gmt_update------修改时间
表名:student
学号:int,姓名:varchar,性别sex,出生日期birthday
CREATE TABLE IF NOT EXISTS `student` ( `ID` INT(15) NOT NULL AUTO_INCREMENT COMMENT '学号', `NAME` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名', `sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别', `birthday` DATETIME DEFAULT NULL COMMENT '出生日期', PRIMARY KEY(`ID`) )ENGINE`student`=INNODB DEFAULT CHARSET=utf8
格式:
格式: CREATE TABLE [IF NOT EXISTS] `表名`( `字段名` 列类型 [属性] [索引] [注释], `字段名` 列类型 [属性] [索引] [注释], ······ `字段名` 列类型 [属性] [索引] [注释] )[表类型] [字符集设置][注释]
常用命令
SHOW CREATE DATABASE ****(数据库名称)-- 查看创建数据库的语句 SHOW CREATE TABLE ****(表名) --查看student数据表的定义语句 DESC ****(表名) -- 显示表的结构
INNODB
- 默认使用
- 节约空间
- 速度较快
MYISAM(早些年使用)
- 早些年使用
- 安全性高
- 事务处理,多表多用户操作
MYISAM | INNODB | |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持(表锁) | 支持 |
外键 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
表空间的大小 | 较小 | 较大,约为MYISAM两倍 |
MYSQL引擎在物理文件的区别
- INNODB在数据库表中只有一个*.frm,以及上级目录下的ibdata文件。
- MYISAM对应文件
- *.frm -- 表结构定义文件
- *.MYD 数据文件(data)
- *.MYL 索引文件(index)
设置数据库表的字符集编码
CHARSET=UTF8
character -set-server=utf8
- 修改表名
ALTER TABLE 旧表名 RENAME AS 新表名
- 增加表的字段
ALTER TABLE 表名 ADD 字段名 列属性
- 修改表的字段(重命名、修改约束!)
ALTER TABLE *****(表名) MODIFY **(字段名) **(列属性) ---修改约束 ALTER TABLE *****(表名) CHANGE ***(旧名字) ***(新名字) ***(列属性) --字段重命名 结论:
CHANGE用来字段重命名,不能修改字段类型和约束
MODIFY不能用于字段,只能修改字段类型和约束
- 删除表的字段
ALTER TABLE ***(表名) DROP ***(列属性)
- 删除表
DROP TABLE IF EXISTS ****(表名) 创建和删除操作尽量加上判断,以免报错
- `` 字段名,使用其包裹起来
- 注释:“--”、/**/
- sql大小写不敏感
- 所有的符号用英文
方式一
在创建表的时候增加约束(麻烦、复杂)
CREATE TABLE `grade`( `gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id', `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称', PRIMARY KEY(`gradeid`) )ENGINE=INNODB DEFAULT CHARSET=utf8 CREATE TABLE `student`( `ID` INT(15) NOT NULL AUTO_INCREMENT COMMENT '学号', `NAME` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名', `SEX` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别', `BIRTHDAY` DATETIME DEFAULT NULL COMMENT '出生日期', `gradeid` INT(10) NOT NULL COMMENT '学生的年级', PRIMARY KEY(`ID`), KEY `FK_gradeid` (`gradeid`), CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`) )ENGINE=INNODB DEFAULT CHARSET=utf8
删除有外键关系的表的时候,必须先删除引用别人的表(从表),再删除被引用的表(主表)
方式二
创建表成功后在添加外键约束
创建表是没有外键,后续添加外键关系公式: ALTER TABLE 表 ADD CONSTRAINT 约束名 FOREIGN KEY(作为外键的列) REFERENCES `哪一个表名`(`哪个字段`)
最佳实践:
- 数据库就是单纯的表,只是用来存数据,只有行(数据)和列(数据)
- 想使用多张表的数据,想使用外键(通过程序去实现)
定义:数据操作语言
-- 插入语句语法: INSERT INTO 表名([字段名1,字段2,字段3])VALUES('值1'),('值2'),('值3')
注意事项:
- 字段和字段之间使用英文逗号隔开
- 字段是可以省略的,但是后面的值必须一一对应
- 可以同时插入多条数据,VALUES 后面的值需要使用英文括号包裹,括号之间要用英文逗号隔开S
update 修改谁? (条件) set原来的值=新值
-- 语法: UPDATE `表名` SET COLNUM_NAME = VALUE,[COLNUM_NAME=VALUE....] WHERE [条件]
条件:where子句运算符,例如:id等于某个值、大于某个值,在某个区间内修改......
操作符会返回布尔值
操作符 | 含义 | 范围 | 结果 |
---|---|---|---|
= | 等于 | 5=6 | false |
<>或!= | 不等于 | 5<>3 | true |
> | 大于 | 5>3 | true |
< | 小于 | 5<3 | false |
<= | 小于等于 | 2<=3 | true |
>= | 大于等于 | 3>=2 | true |
BETWEEN...AND | 在某个范围内 | [2,5] | |
AND | &&(我和你) | 5>1and1>2 | false |
OR | ||(我或你) | 5>1or 1>2 | true |
注意事项:
- colnum_name是数据库的列,尽量带上``
- 条件,筛选的条件:如果没有指定则会修改所有的列
- value,是一个具体的值,也可以是一个变量
- 多个设置的属性之间,使用英文逗号隔开
DELETE 命令
语法:
DELETE FROM ***(表名) [WHERE 条件]
TRUNCATE 命令
语法:
TRUNCATE ***(表名)
作用:
完全清空一个数据库表,表的结构和索引约束不变!
DELETE 与 TRUNCATE 的区别
- 相同点:
- 都能上次删除数据
- 都不会删除表的结构
- 不同点
- TRUNCATE 重新设置自增列,计数器归0
- TRUNCATE 不会影响事务
CREATE TABLE `teacher`( `id` INT(8) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) NOT NULL, PRIMARY KEY(id) )ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO `teacher`(`name`) VALUE('1'),('2'),('3') DELETE FROM `teacher` --不会影响自增 TRUNCATE TABLE `teacher` --自增归0
DELETE删除的问题,重启数据库的现象:
- INNODB,自增列会从1开始 (存在内存当中,断电即失)
- MyISAM, 继续从上一个自增量开始(存在文件中的,不会丢失)
- 所有的查询操作都用它
- 简单、复杂的查询都可以完成
- 数据库中最核心的语言,最核心的语句
- 使用频率最高的语句
查询全部字段: SELECT * FROM *****(表名) 查询指定字段 SELECT ` * `(表中字段),` * `,.... FROM ***(表名) 别名,给结果起一个名字(字段或表) SELECT ` * `(表中字段) AS ***(别名),` * ` AS ***(别名),.... FROM ***(表名) AS ****(别名) 函数 CONCAT(A,B) SELECT CONCAT('**(连接的字符串)',****(表中字段)) AS ***(别名) FROM ****(表名) 注意: 起别名只在自己展示界面窗口那边展示别名,但是重新打开表后,展示的不是别名而是自己刚开始定义的变量名;也就是说,别名只是我们在查询的时候看的。 CONCAT中的A,使用英文单引号框起来的,不是``!。
语法: SELECT ***(字段) .....FROM ****(表) 有的时候,列名字不是那么见名知意,我们起别名 AS: 字段名 AS 别名 表名 AS 别名
作用: 去除SELECT查询结果中重复的数据 语法: SELECT DISTANCT `表中字段` FROM `表名`
SELECT * FROM `result` --查询全部 SELECT `studentno` FROM result --查询某一列 SELECT DISTINCT `studentno` FROM result --去重
数据列的表达式: SELECT VERSION() --查询系统版本(函数) SELECT 100*3-1 AS 计算结果 --用于计算(表达式) SELECT @@AUTO_INCREMENT_INCREMENT --查询自增步长 SELECT `表中字段`+1 AS '别名' FROM 表名
数据库中的表达式:
- 文本值
- 列
- NULL
- 函数
- 计算表达式
- 系统变量
SELECT + 表达式
作用:检索数据中符合条件的值
搜索的结果由一个或者多个表达式组成! 结果 布尔值
逻辑运算符:
运算符 | 语法 | 描述 |
---|---|---|
and && | A and B A&&B | 逻辑与,两个都为真,结果为真 |
or || | A or B A||B | 逻辑或,一个为真,结果为真 |
Not ! | NOT A !A | 逻辑非,真为假,假为真 |
比较运算符
运算符 | 语法 | 描述 |
---|---|---|
IS NULL | A IS NULL | 如果操作符为NULL,结果为真 |
IS NOT NULL | A IS NOT NULL | 如果操作符不为NULL,结果为真 |
BETWEEN | A BETWEEN B AND C | 若A在B和C之间,则结果为真 |
LIKE | A LIKE B | SQL匹配,如果A匹配B,则结果为真 |
IN | A IN(A1,A2,A3.....) | 假设a在a1,或者a2......其中的某一个值中,结果为真 |
‘ **% ** ’ ‘ _ ’:
- %:代表0到任意个字符
- _:代表一个字符
SELECT `表中字段`, `表中字段` ,....FROM `表名` WHERE `表中字段` LIKE '*(模糊查询的内容)%' 注:出现的内容为以*开头,后面的长度不限 SELECT `表中字段`, `表中字段` ,....FROM `表名` WHERE `表中字段` LIKE '*(模糊查询的内容)_' 注:出现的内容以*开头,后面只有一个字符,如果后面又两个字符则用两个__,或者用% 说明: _ % 可以放在模糊查询的前面,也可以放在后面,根据自己的需求进行代码的书写。
IN :
- 后面加一个或者多个具体的值
SELECT `表中字段`, `表中字段` FROM `表名` WHERE `表中字段` IN ('***(查询的具体内容)',`****`.....);
NULL NOT NULL
查询表中字段1为空的值 SELECT `表中字段`, `表中字段` FROM `表名` WHERE 表中字段1='' OR 表中字段1 IS NULL 查询表中字段1不为空的值 SELECT `表中字段`, `表中字段` FROM `表名` WHERE 表中字段1 IS NOT NULL
操作 | 描述 |
---|---|
INNER JOIN | 如果表中至少有一个匹配,返回行 |
LEFT JOIN | 会从左表中返回所有的值,即使右表中没有匹配 |
RIGHT JOIN | 会从右表中返回所有的值,即使左表中没有匹配 |
JOIN(连接的表) ON(判断的条件) -- 连接查询
WHERE --等值查询
定义:自己与自己的表连接
核心:一张表拆分成两张一样的表
categoryid | categorName |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
pid | categoryid | categoryName |
---|---|---|
3 | 4 | 数据库 |
2 | 8 | 办公信息 |
3 | 6 | web开发 |
5 | 7 | ps技术 |
查询弗雷对应子类的关系
父类 | 子类 |
---|---|
信息技术 | 办公信息 |
软件开发 | 数据库 |
软件开发 | web开发 |
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] [WHERE....] ---指定结果需满足的条件 [GROUP BY ....] ---指定结果按照那几个字段来分组 [HAVING] --- 过滤分组的记录必须满足的次件 [ORDER BY.....] --指定查询记录按一个或多个条件排序 [LIMIT {[OFFSET,]ROW_COUNTOFFSET OFFSET}]; --指定查询记录从那条到那条 } 上述顺序不能变注意:[]:表示可选,{}:表示必选
SELECT 去重 要查询的字段 from 表名(表和字段可以取别名)
XX JOIN 要连接的表 on 等值判断
where (具体的值, 子查询语句)
group by (通过那个字段来分组)
having (过滤分组后的信息,条件和where一样,位置不同)
order by ...(通过那个字段排序)【升序/降序】
limit startindex pagesize
--测试代码: CREATE TABLE `test`( `categoryid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `pid` INT(10) NOT NULL, `categoryName` VARCHAR(50) NOT NULL, PRIMARY KEY (`categoryid`) )ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT t.`categoryName`, s.`categoryName` FROM `test` AS t, `test` AS s WHERE s.pid=t.categoryid
排序:
升序:ASC
降序:DESC
语法:
ORDER BY `表中字段` ASC[DESC]
分页:
作用:缓解数据库压力,给人体验更好,避免瀑布流
语法:
LIMIT 起始值, 页面大小(pageSize) 计算: --【pageSize:页面大小】 --【(n-1)*passageSize:起始值】 --【n:当前页】 --【数据总数/页面大小=总页数】
WHERE (这个值是计算出来的)
本质:
在WHERE语句中嵌套一个子查询语句
WHERE(SELECT FROM *)
由里及外
**常用函数:** 数学运算: SELECT ABS(-8) --取绝对值 SELECT CEILING(9.4) --向上取整 SELECT FLOOR(9.4) --向下取整 SELECT RAND() --返回一个0-1之间的随机数 SELECT SIGN(0) --判断一个数的符号,负数返回-1,正数返回1 字符串函数 SELECT CHAR_LENGTH('*****') --字符串长度 SELECT CONCAT('**','**','**') --拼接字符串 SELECT INSERT('****',1,2,'***') --查询,从某个位置开始替换某个长度 SELECT LOWER('ADSAFSF') --转换成小写 SELECT UPPER('qadaddf') --转换成大写 SELECT INSER('***','*') --返回第一次出现的子串的索引、 SELECT REPLACE('*****','****1','****2') --替换出现的指定字符串 SELECT SUBSTR('******',4(开始位置),2(截取长度)) --截取原字符串 SELECT REVERSE('********') --反转 时间和日期函数: SELECT CURRENT_DATE() --获取当前日期 SELECT CURDATE() --获取当前日期 SELECT NOW() --获取当前时间 SELECT LOCALTIME() --返回本地时间 SELECT SYSDATE() --返回系统时间 SELECT YEAR(NOW()) SELECT MONTH(NOW()) SELECT DAY(NOW()) SELECT HOUR(NOW()) SELECT MINUTE(NOW()) SELECT SECOND(NOW()) 系统: SELECT SYSTEM_USER() SELECT USER() SELECT VERSION()
函数名称 | 描述 |
---|---|
SUM() | 求和 |
COUNT() | 计数 |
AVG() | 平均数 |
MAX() | 最大值 |
MIN() | 最小值 |
...... | 其他 |
SELECT COUNTz(指定列,表中字段) FROM ***(表名) --会忽略所有的null值 SELECT COUNT(*) FROM ***(表名) --不会忽略null值,本质:计算行数 SELECT COUNT(1) FROM ***(表名) --不会忽略所有的null值,本质:计算行数
MD5:增强算法复杂度和不可逆性
破解原理:网站后有一个字典,MD5加密后的值,加密的前值
CREATE TABLE `test`( `id` int(4) NOT NULL, `name` VARCHAR(20) NOT NULL, `pwd` VARCHAR(20) NOT NULL, PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 --明文密码 INSERT INTO test VALUES(1,'张','123456'),(2,'李','123456'), (3,'王','123456') --加密 UPDATE test SET pwd=MD5(pwd) WHERE id=1 UPDATE test SET pwd=MD5(pwd)---加密全部的密码 --插入时加密 INSERT INTO test VALUES(4,'XX',MD5('123456')) -- 校验:将用户传递的密码进行MD5加密,然后比对加密后的值 SELECT * FROM test WHERE `name`='XX' AND pwd=MD5('123456')
什么是事务:要么都成功,要么都失败
事务原则:
- ACID原则(如下)
- 原子性:两个步骤一起成功或者一起失败,不能只发生其中一个动作(要么都成功,要么都失败)
- 一致性:针对一个事务操作前与操作后的状态一致
- 隔离性:多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰
- 持久性:事务结束后数据不会随着外界原因导致数据丢失,事务没有提交,便恢复到原状;事务提交便持久化到数据库中。事务一旦提交不可逆。
脏读:
定义:一个事务读取了另外一个事务未提交的数据
不可重复读:
定义:在一个事务内读取表中的某一行数据,多次读取结果不同(不一定错,场合不对)
虚读(幻读):
定义:一个事务内读取到别的事务插入的数据,导致前后读取不一致
MySQL默认开启事务自动提交 SET autocommit = 0 /*关闭*/ SET autocommit = 1 /*开启*/ --手动处理事务 START TRANSACTION --标记一个事务的开始,从这个之后的sql都在同一个事务当中 INSERT XX INSERT XX (上面两行都成功才算成功,否则是失败的) --提交:持久化(成功!) COMMIT --回滚:回到原来的样子(失败!) ROLLBACK --事务结束 SET autocommit = 1 --开启自动提交 SAVEPOINT 保存点名 --设置一个事物的保存点 ROLLBACK TO SAVEPOINT 保存点名 --回滚到保存点 RELEASE SAVEPOINT 保存点名 --撤销保存点
定义:帮助MySQL高效获取数据的数据结构,提取句子主干,九二一获得索引的本质:索引就是数据结构
- 主键索引:PRIMARY KEY
- 唯一标识,不可重复,只能有一个列作为主键
- 唯一索引:UNIQUE KEY
- 避免重复的列出现,可以重复,多个列都可以标识位唯一索引
- 常规索引:KEY/INDEX
- 默认的,index、key关键字来设置
- 全文索引:FULLTEXT
- 在特定的数据库引擎下才有,MyISAM
- 快速定位数据
--显示所有的索引信息: SHOW INDEX FROM ***(表名) --增加一个全文索引 ALTER TABLE ***(库名).****(表名) ADD FULLTEXT INDEX `******(索引名)`(`****(列名)`) --EXPLAIN 分析sql执行状况 EXPLAIN SELECT * FROM ****(表名) --非全文索引 EXPLAIN SELECT * FROM ***(表名) WHERE MATCH(****(列名)) AGAINST('全文索引')
索引在小数据量师,用处差别不大,在大数据时差别很明显。
- 索引不是越多越好
- 不要对经常变动的数据加索引
- 小数据量的表不需要加索引
- 索引一般用来常用来查询的字段上!
索引的数据机构:
- Hash类型的索引
- Btree:INNODB的默认数据结构
SQL命令操作:
用户表:mysql.user
本质:对这张表进行增删改查
--创建用户 CREATE USER ***(用户名) IDENTIFIED BY '密码' --修改当前用户的密码 SET PASSWORD = PASSWORD('******(密码)') --修改指定用户的密码 SET PASSWORD FOR *****(用户名)= PASSWORD('******(密码)') --用户重命名 RENAME USER ****(原名) TO *****(新名) --用户授权命令,授予全部的权限,库.表(一般不用,用勾选),不能给别人授权 GRANT ALL PRIVILEGES ON *.* --查询权限(指定用户) SHOW GRANTS FOR ****(用户名) SHOW GRANTS FOR root@localhost --撤销权限 REVOKE 那些权限 在那个库 给谁撤销 REVOKE ALL PRIVILEGES ON *.*(指定的,否则是全局的) FROM ****(用户名) --删除用户 DROP USER ****(用户名)
数据库的备份
- 保证重要数据不丢失
- 数据转移A-->B
MySQL数据库备份的方式:
mysqldump -hlocalhost -uroot -p******(密码) **(库名) **(表名)>D:/...(导出位置) mysqldump -h(主机) -u(用户名) -p(密码) 数据库 表1 表2 表3 ... >物理磁盘位置/文件名 #不加表名就是导出数据库 #导入 #登录的情况下,切换到指定的数据库 source ****(备份文件) mysql -u用户名 -p密码 库名< 备份文件
糟糕的数据库:
- 数据冗余,浪费空间
- 数据库插入和删除比较复杂,容易出现异常(屏蔽使用物理外键)
- 程序的性能差
良好的数据库设计:
- 节省内存空间、
- 保证数据的完整性
- 方便开发系统
为什么:
- 信息重复
- 更新异常
- 插入异常
- 无法正常显示异常
- 删除异常
- 丢失有效信息
三大范式
- 第一范式
- 原子性:保证每一列不可再分
- 第二范式
- 前提满足第一范式
- 每张表只描述一件事情
- 第三范式
- 前提满足第二范式
- 确保数据表中每一列数据和主键直接相关,而不能间接相关
规范和性能的问题:
关联查询的表不能超过3张表
- 考虑商业化的需求和目标(成本和目标体验),数据库的性能更重要
- 在规范性能的问题的时候,适当考虑一下规范性
- 故意增加某些表的冗余字段(从多张表查询变成单表查询)
- 故意增加一些计算列(从大数据量降低为小数据量的查询:索引)
定义:java数据库的连接,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC时Sun Microsystem的商标。通常说JDBC是面向关系型数据库的。
import java.sql.*; public class test { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.加载驱动 Class.forName("com.mysql.jdbc.Driver"); //固定写法,加载驱动 //2.用户信息和url school:这个是数据库 String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true"; String username="root"; String password="123456"; //3.连接成功,数据库对象,Connection 代表数据库 Connection connection=DriverManager.getConnection(url,username,password); //4.执行SQL的对象statement 执行sql的对象 Statement statement=connection.createStatement(); //5.执行SQL对象 String sql="SELECT * FROM test"; ResultSet resultSet=statement.executeQuery(sql);//返回结果集 while(resultSet.next()){ System.out.println("categoryid="+resultSet.getObject("categoryid")); System.out.println("pid="+resultSet.getObject("pid")); System.out.println("categoryName="+resultSet.getObject("categoryName")); } } }
步骤总结:
- 加载驱动
- 连接数据库DriverManager
- 获得执行sql对象 Statement
- 获得返回的结果集
- 释放连接
DriverManager:
//DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //不推荐,这样的话会注册两次 Class.forName("com.mysql.jdbc.Driver"); //固定写法,加载驱动 //connection:代表数据库 connection.rollback(); connection.commit(); connection.setAutoCommit();
URL
String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true"; //mysql 默认端口号:3306 //jbdc:mysql(协议)://主机地址:端口号/数据库名?参数1&参数2&参数3 //oralce 默认端口号:1521 //jbdc:oracle:thin:@localhost:1521:sid
Statement执行SQL的对象 PrepareStatement执行SQL对象
String sql="SELECT * FROM test";//编写SQL statement.excuteQuery();//查询操作,返回一个ResultSet(结果集) statement.excute();//执行任何SQL statement.executeUpdate();//更新、插入、删除、都用这个,返回一个受影响的函数
ReseltSet查询结果集:封装了所有的查询结果
获得指定的数据类型:
resultset.getobject();//在不知道的情况下使用 //如果知道列的类型使用指定的类型 resultset.getString(); resultset.getInt(); resultset.getFloat(); resultset.getDate(); ... //遍历,指针 resultSet.beforeFirst(); // 移动到最前面 resultSet.afterLast(); // 移动到最后面 resultSet.next(); // 移动到下一个数据 resultSet.previous(); // 移动到前一行 resultSet.absolute(row); // 移动到指定行
释放资源
//释放连接 resultSet.close(); statement.close(); connection.close();//耗费资源,用完关闭
定义:jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
statement对象的方法:
- executeUpdate(),用于向数据库发送增删改的SQL语句,executeUpdate()执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
- executeQuery(),用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
statement st=connection.creatstatement(); String sql="insert into user(...) values(...)"; int num=st.executeUpdate(sql); if(num>0){ System.out.println("success"); }
statement st=connection.creatstatement(); String sql="delect from user where id=1"; int num=st.executeUpdate(sql); if(num>0){ System.out.println("success"); }
statement st=connection.creatstatement(); String sql="update user set name='***' where name='***'"; int num=st.executeUpdate(sql); if(num>0){ System.out.println("success"); }
statement st=connection.creatstatement(); String sql="select * from user where id=1"; ResultSet re=st.executeQuery(sql); where(rs.next()){ //根据获取的数据类型,分别调用rs相应方法映射到java对象中。 }
//插入 public class TestInsert { public static void main(String[] args) throws SQLException { Connection conn=null;//获取数据库的连接 Statement st=null;//获取sql的执行对象 ResultSet rs=null; try { conn=JdbcUtils.getConnection(); st=conn.createStatement(); String sql="INSERT INTO test(categoryid,pid,categoryName)" + "VALUES (10,4,'美术')"; int i=st.executeUpdate(sql); //受影响的行数 if(i>0){ System.out.println("Success"); } } catch (SQLException e) { e.printStackTrace(); }finally { JdbcUtils.release(conn,st,rs); } } }
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=123456
SQL存在漏洞,会被攻击导致数据泄露, SQL会被拼接
防止SQL注入的本质:把传递进来的参数当作字符,如果其中存在转文字,会被直接转义,可以有效的避免SQL注入。