赞
踩
JavaEE : 企业级Java开发 Web结构:
前端 :(页面 :展示,数据!)
后台 :(连接点 :链接数据库JDBC,连接前端(控制,控制试图跳转,和给前端传 递数据))
数据库(存数据,Text,word,Excel)
只会写代码,基本混饭吃!
操作系统,数据结构与算法,当一个不错得程序员!
离散数学,数字电路,体系结构,编译原理。+实战经验, 高级的优秀程序员
1、岗位需求
2、现在的世界,大数据时代~,得数据者得天下。
3、被迫需求:存数据
4、数据库是所有软件体系种最核心得存在 DBA
数据库(DB,Database)
概念:数据仓库,软件,安装在操作系统(Windows,Linux,mac、…)之上!SQL,可以存储大量数据。500万!
作用:存储数据,管理数据
关系型数据库 : (SQL)
非关系型数据库 :(NoSQL) Not Only
DBMS(DataBase Management System ) 数据库管理系统
MySQL是一个关系型数据库管理系统
前世:瑞典MySQL AB公司
今生:属于Oracle旗下产品
MySQL是最好的RDBMS(Relational DataBase Management System,关系型数据库管理系统)应用软件之一。
开源的数据库软件~
体积小、速度快、总体拥有成本低,招人成本比较低,所有人必须会~
中小型网站、或者大型网站,集群!
官网:https://www.mysql.com
安装建议:
1、尽量不要用exe,会添加到注册表种,卸载比较麻烦
2、尽可能使用压缩包安装,只需要自己配下环境变量就行~
教程:
1、解压
2、把压缩包放到电脑目录下,要记住放哪里了~
3、配置环境变量
4、新建mysql.ini配置文件
[mysqld] # 设置3306端口 port=3306 # 设置mysql的安装目录 basedir=D:/mysql/mysql-8.0.28-winx64 # 设置mysql数据库的数据的存放目录 (data文件夹如果没有的话会自动创建) datadir=D:/mysql/mysql-8.0.28-winx64/data # 允许最大连接数 max_connections=200 # 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统 max_connect_errors=10 # 服务端使用的字符集默认为UTF8 character-set-server=utf8 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 默认使用“mysql_native_password”插件认证 default_authentication_plugin=mysql_native_password # 跳过密码认证 skip-grant-tables [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [client] # 设置mysql客户端连接服务端时默认使用的端口 port=3306 default-character-set=utf8
5、启动cmd(管理员模式)
6、进入解压文件夹种的bin目录
cd /d D:\mysql\mysql-8.0.28-winx64\bin # 这是我自己的目录
7、初始化MySQL
mysqld --initialize-insecure
8、安装MySQL
mysqld --install
9、启动MySQL服务
net start mysql # 启动
net stop mysql # 停止
# 如果安装失败了,以下命令删除mysql服务,重新按照以上步骤进行操作
sc delete mysql
10、进入MySQL,并修改密码
mysql -uroot -p -- 进入命令,不输密码,跳过验证
-- 进入后,将密码修改为123456
mysql>update mysql.user set authentication_string=password('123456') where user='root' and Host='localhost';
mysql>flush privileges;
11、注释掉ini配置文件种的跳过密码认证:skip-grant-tables
12、将MySQL目录种的bin文件夹加入环境变量的Path变量中~
13、重启MySQL服务,连接输入密码进入MySQL,大功告成!
命令行连接:
mysql -uroot -p123456 -- 出现mysql>的字样则连接成功! -- --------------------------------- -- 所有语句使用;结尾 mysql>show databases; -- 查看所有数据库 mysql>use mysql; -- 切换数据库 mysql>show tables; -- 查看数据库所有的表 mysql>describe student; -- 查看当前数据库中的名为student的表结构 mysql>create database school; -- 创建一个名为school的数据库 mysql>exit --退出连接 -- 单行注释 /* 多行 注释 */
数据库语言:
DDL 数据库定义语言
DML 数据库**管理(操作)**语言
DQL 数据库查询语言
DCL 数据库控制语言
数据库 > 库中表 > 表中数据(字段,值)
MySQL关键字不区分大小写
1、创建数据库
mysql>create database [if not exists] school;
2、使用/切换数据库
-- 为了避免和和特殊字符重合,我么使用自己定义的字符时尽量用``符号括起来(TAB键的上面)
mysql>use school;
3、删除数据库
mysql>drop database [if exists] school;
学习思路:
在SQLyoug中使用后,对比SQLyog的历史记录,可以让我们快速的查看命令
常用的语法和关键字须记住!
数值
字符串
时间日期
java.util.Date
NULL
Unsigned:
zerofill:
自增(AUTO_INCREMENT):
非空: NOT NULL,NULL
DEFAULT(默认):
拓展:
/* 每一个表,都必须存在以下五个字段!(未来做项目用的,表示每一个记录存在意义!)
这是阿里巴巴规范里面的
id 主键
`verson` 乐观锁
is_delete 伪删除
gmt_create 创建时间
gmt_update 修改时间
*/
CREATE 的语法:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table_name
[(
COLUMN_DEFINITION,(这个有可选属性)
...
)]
[TABLE_OPTIONS]
[SELECT_STATEMENT];
-- 目标 : 创建一个school数据库 -- 创建学生表(列,字段) 使用SQL创建 -- 学号int 登录密码varchar(20) 姓名varchar(30),性别varchar(2),出生日期(datetime),家庭住址(address), 邮箱email -- 注意,使用英文(),表的名称和字段尽量用``括起来 -- AUTO_INCREMENT自增 -- 字符串用单引号或双引号括起来! -- 所有的语句后面加,(英文的),最后一个不加 -- PRIMARY KEY 主键,一般一个表只有一个唯一的主键! CREATE TABLE `school`( `id` INT NOT NULL AUTO_INCREMENT COMMENT '学号', `name` VARCHAR(30) NOT NULL COMMENT '姓名', `password` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码', `sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别', `birthday` DATETIME NOT NULL COMMENT '出生日期', `address` VARCHAR(100) NULL COMMENT '家庭住址', `email` VARCHAR(20) NULL COMMENT '邮箱', PRIMARY KEY(`id`) )ENGINE = INNODB, CHARSET = utf8;
格式
create table `表名`(
`字段名` 数据类型 [属性] [索引] [注释],
... ,
`字段名` 数据类型 [属性] [索引] [注释]
)ENGINE = 引擎名, CHARSET = 字符集, [注释];
-- 关于数据库引擎
/*
INNODB 默认使用~
MYISAM 早些年使用的
*/
引擎类型 | MYISAM | INNODB |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
外键约束 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
表空间的大小 | 较小 | 较大,约为2倍 |
常规使用操作:
在物理空间存在的位置
所有的数据库文件都存在data目录下,一个文件夹就对应一个数据库
本质还是文件的存储!
MySQL引擎在物理文件上的区别:
设置数据库表的字符集编码
CAHRSET = utf8
不设置的话,会是MySQL默认的字符集编码~(不支持中文!)
MySQL的默认编码是Latin1,不支持中文
可以在my.ini配置文件中设置默认编码:
character-set-server = utf8
修改
-- 修改表名 ALTER TABLE 旧表名 RENAME AS 新表名;
ALTER TABLE `school` RENAME AS `school1`;
-- 增加表的字段 ALTER TABLE 表名 ADD 字段名 列属性;
ALTER TABLE school1 ADD `phone` INT(11);
-- 修改表的字段 (重命名,修改约束!)
ALTER TABLE `school1` CHANGE `phone` `phone1` INT(1);-- 重命名
ALTER TABLE `school1` MODIFY `phone` VARCHAR(11);-- 修改约束
-- 删除表的字段
ALTER TABLE `school1` DROP `phone1`;
删除
-- 删除表(如果存在再删除)
DROP TABLE IF EXISTS `school1`;
所有的创建和删除操作尽量加上判断,以免报错~
注意点:
在创建表的时候,增加约束(麻烦,比较复杂)
CREATE TABLE `grade`( `gradeid` INT NOT NULL AUTO_INCREMENT COMMENT '班级id', `gradename` VARCHAR(30) NOT NULL COMMENT '班级名称', PRIMARY KEY(`gradeid`) )ENGINE = INNODB, CHARSET = utf8; -- student表的gradeid字段,要去引用年级表的gradeid字段 -- 定义外键key -- 给外键增加约束(执行引用),references 引用 CREATE TABLE `student`( `id` INT NOT NULL AUTO_INCREMENT COMMENT '学号', `name` VARCHAR(30) NOT NULL COMMENT '姓名', `password` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码', `sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别', `birthday` DATETIME NOT NULL COMMENT '出生日期', `gradeid` INT NOT NULL COMMENT '班级id', `address` VARCHAR(100) NULL COMMENT '家庭住址', `email` VARCHAR(20) NULL COMMENT '邮箱', PRIMARY KEY(`id`), KEY `FK_gradeid` (`gradeid`), CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`) )ENGINE = INNODB, CHARSET = utf8;
删除又外键关系的表的时候,必须要先删除引用别人的表(从表),再删除被引用的表(父表)
方式二 :创建表成功之后,增加外键约束
CREATE TABLE `grade`( `gradeid` INT NOT NULL AUTO_INCREMENT COMMENT '班级id', `gradename` VARCHAR(30) NOT NULL COMMENT '班级名称', PRIMARY KEY(`gradeid`) )ENGINE = INNODB, CHARSET = utf8; CREATE TABLE `student`( `id` INT NOT NULL AUTO_INCREMENT COMMENT '学号', `name` VARCHAR(30) NOT NULL COMMENT '姓名', `password` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码', `sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别', `birthday` DATETIME NOT NULL COMMENT '出生日期', `gradeid` INT NOT NULL COMMENT '班级id', `address` VARCHAR(100) NULL COMMENT '家庭住址', `email` VARCHAR(20) NULL COMMENT '邮箱', PRIMARY KEY(`id`) )ENGINE = INNODB, CHARSET = utf8; -- 创建表的时候没有外键关系 ALTER TABLE `student` ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`); -- ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY (从表字段) REFERENCES 主表名 (主表字段)
以上的操作都是物理外键,数据库级别的外键,我们不建议使用!(避免数据库过多造成困扰)
最佳实践:
**数据库意义:**数据存储,数据管理
DML语言:数据操作(管理)语言
insert 语法:
INSERT [LOW_PRIORITY |DELAYED| HIGH_PRIORITY]
[IGNORE][INTO]tbl_name[(col_name,...)]
VALUES ({expr| DEFAULT},...),(...),...
[ON DUPLICATE KEY UPDATEcol_name=expr,... ]
INSERT [LOW_PRIORITY |DELAYED| HIGH_PRIORITY]
[IGNORE][INTO]tbl_name
SET col_name={expr| DEFAULT},... ]
INSERT [LOW_PRIORITY | HIGH_PRIORITY]
[IGNORE][INTO]tbl_name[(col_name,...)]
SELECT ...[ON DUPLICATE KEY UPDATEcol_name=expr,... ]
-- 插入语句(添加)
-- insert into 表名([字段1],[字段2],[字段3],...) values('值1','值2','值3',...);
INSERT INTO `grade`(`gradename`) VALUES('大一'),('大二'),('大三'),('大四');
-- 一个字段插入多个值,每个值用括号括住,并用逗号分开
-- 一般写插入语句,我们一定要将字段和值一一对应!
-- 插入多个字段
INSERT INTO `student`(`name`,`password`,`sex`)
VALUES('赵六','aaaaaa','男'),('吴七','bbbbbb','女'),('沈八','cccccc','男');
语法:insert into 表名([字段1],[字段2],[字段3],...) values('值1','值2','值3',...);
注意事项:
1. 字段和字段之间使用英文隔开
1. 字段是可以省略的,但是后面的值必须一一对应,一个字段也不能少
1. 可以同时插入多条数据,VALUES后面的值,先括住,再用逗号隔开即可 `VALUES(),(),(),...`
update 语法:
-- ================ 单表更改 ===================
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]
-- ================ 多表更改 ===================
UPDATE [LOW_PRIORITY] [IGNORE] table_references
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
-- 修改学生名字,带条件
UPDATE `student` SET `name` = '东方红' WHERE `name` = '张三';
-- 修改学生名字,不带条件,会全部修改!
UPDATE `student` SET `name` = '东方红';
-- 修改多个属性,用逗号隔开
UPDATE `student` SET `name` = '黄河',`email` = '1059615162@qq.com' WHERE `id` = 1;
-- 语法:
-- UPDATE 表名 SET column_name = value,[column_name = value,......] [where 条件]
条件:where子句 运算符 id等于某个值,大于某个值,在某个区间内修改…
操作符会返回 布尔值
操作符 | 含义 | 例子 | 结果 |
---|---|---|---|
= | 等于 | 5 = 6 | false |
<>或!= | 不等于 | 5 <> 6 或5!= 6 | true |
> | 大于 | 5 > 6 | false |
< | 小于 | 5 < 6 | true |
>= | 大于等于 | 5 >= 6 | false |
<= | 小于等于 | 5 <= 6 | true |
BETWEEN…AND… | 在某个范围内(闭区间) | BETWEEN 5 AND 6 | [5,6] |
AND | 和(&&) | 5 < 6 AND 3 > 5 | false |
OR | 或(||) | 5 < 6 AND 3 > 5 | true |
-- 通过多条件定位数据
UPDATE `student` SET `name` = '长江' WHERE `name` = '东方红' AND `sex` = '女';
语法:UPDATE 表名 SET column_name = value,[column_name = value,......] [where 条件];
注意:
UPDATE `student` SET `birthday` = CURRENT_TIME WHERE `id` BETWEEN 2 AND 4;
delete 命令
语法:delete from 表名 [where 条件]
-- 删除数据(避免这样操作,删库跑路)
delete from `student`;
-- 删除指定数据
delete from `student` where `id` = 1;
TRUNCATE 命令
作用:完全清空一个数据表,表的结构和索引不会变!
-- 清空student 表
TRUNCATE `student`;
delete 和 truncate 的区别
-- 测试DELETE 和 TRUNCATE 的区别
CREATE TABLE `test`(
`id` INT NOT NULL AUTO_INCREMENT COMMENT 'id',
`coll` VARCHAR(30) NOT NULL COMMENT 'coll',
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;
INSERT INTO `test` (`coll`) VALUES('1'),('2'),('3');
DELETE FROM `test` -- 不会影响自增
TRUNCATE TABLE `test` -- 自增会归零
DELETE删除的问题
删除后重启数据库的现象:
( Data Query Language : 数据查询语言 )
straight distinct high_priorty rollup
Select 的完整语法:
SELECT [ALL | DISTINCT | DISTINCTROW] [HIGH_PRIORTY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [,select_expr ...] [FROM table_references PARTITION partition_list] [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]
-- 查询全部学生 SELECT 字段 FROM 表名
SELECT * FROM `student_information`;
-- 查询指定字段
SELECT `name` FROM `student_information`;
-- 别名,给结果起一个名字,可以给起别名,也可以给表起别名
SELECT `name` AS 姓名,`favorite` AS 兴趣爱好 FROM `student_information`;
-- 函数 CONCAT() 字符串拼接函数
SELECT CONCAT('姓名:',`name`,' 兴趣爱好:',`favorite`) AS 新名字 FROM `student_information`;
语法:SELECT 字段,... from 表名
有的时候,列名字不是那么的见名知意,所以我们可以起别名
关键字:AS
用法:
去重 distinct
作用:去除SELECT查询出来的结果中重复的数据,只显示一条
-- 查询一下哪些同学参加了考试
SELECT * FROM `student_score` -- 查看成绩表
SELECT `s_id` FROM `student_score` -- 查询有哪些同学参加了考试
SELECT DISTINCT `s_id` FROM `student_score` -- 发现重复数据,去重
数据库的列(表达式)
-- 查询一下哪些同学参加了考试
SELECT * FROM `student_score` -- 查看成绩表
SELECT `s_id` FROM `student_score` -- 查询有哪些同学参加了考试
SELECT DISTINCT `s_id` FROM `student_score` -- 发现重复数据,去重
SELECT VERSION() -- 查看系统版本号(函数)
SELECT 100*3-1 AS 计算结果 -- 用来计算(表达式)
SELECT @@auto_increment_increment -- 查询自增的步长(变量)
-- 查看学院考试成绩并+1分
SELECT `s_id`,`score`+1 AS 提分后 FROM `student_score`
数据库中的表达式: 文本值,列,NULL,函数,计算表达式,系统变量,… …
select 表达式
from 表名
作用:检索数据中符合条件
的值
搜索的条件由一个或多个表达式组成!结果 布尔值
逻辑运算符
运算符 | 含义 | 描述 |
---|---|---|
AND && | a AND b a && b | 逻辑与,全部为真,结果为真 |
OR || | a OR b a || b | 逻辑或,一个为真,结果为真 |
NOT ! | NOT a !a | 逻辑非,真为假,假为真 |
尽量使用英文字母
-- ======================= where ============================= SELECT `s_id`,`score` FROM `student_score` -- 查询考试成绩在60-75之间 SELECT `s_id`,`score` FROM `student_score` WHERE `score`>=60 AND `score`<=75 -- and && SELECT `s_id`,`score` FROM `student_score` WHERE `score`>=60 && `score`<= 75 -- 模糊查询(基于区间) SELECT `s_id`,`score` FROM `student_score` WHERE `score` BETWEEN 60 AND 75 -- 除了12341学生外的学生成绩 SELECT `s_id`,`score` FROM `student_score` WHERE `s_id` != 12341 -- != NOT SELECT `s_id`,`score` FROM `student_score` WHERE NOT `s_id` = 12341
模糊查询
运算符 | 语法 | 描述 |
---|---|---|
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在a1,a2,a3其中的某一个值中,结果为真 |
-- ======================= 模糊查询 ============================= -- like结合 通配符 %(0 - 任意个字符),_(一个字符) -- 查询姓康的学生 SELECT `id`,`name` FROM `student_information` WHERE `name` LIKE '康%'; -- 查询康姓且两字的学生 SELECT `id`,`name` FROM `student_information` WHERE `name` LIKE '康_'; -- 查询姓赵的学生 SELECT `id`,`name` FROM `student_information` WHERE `name` LIKE '赵%'; -- 查询detail中含有‘健康’的学生 SELECT `id`,`name` FROM `student_information` WHERE `detail` LIKE '%健康'; -- =================== IN (具体的一个或多个的值)=================== -- 查询id为12341,12342学员 SELECT `id`,`name` FROM `student_information` WHERE `id` IN (12341,12342); -- 查询age为19和18的学生 SELECT `id`,`name` FROM `student_information` WHERE `age` IN (18,19); -- IS NULL,IS NOT NULL -- 查询detail不为空的学生 SELECT `id`,`name` FROM `student_information` WHERE `detail` IS NOT NULL; -- 查询detail为空的学生 SELECT `id`,`name` FROM `student_information` WHERE `detail` IS NULL;
Join对比
-- ============ Join 对比 ============== -- 查询学号,姓名,分数 -- Inner Join SELECT si.`id`,`name`,`score` FROM `student_information` si INNER JOIN `student_score` ss ON si.`id` = ss.`s_id` -- Left Join SELECT si.`id`,`name`,`score` FROM `student_information` si LEFT JOIN `student_score` ss ON si.`id` = ss.`s_id` -- Right Join SELECT si.`id`,`name`,`score` FROM `student_information` si RIGHT JOIN `student_score` ss ON si.`id` = ss.`s_id`
操作 | 描述 |
---|---|
Inner Join | 返回两个表中共同有的值,只有一个表有则不返回 |
Left Join | 会从左表中返回所有的值,即使右表中没有匹配(返回NULL嘛) |
Right Join | 会从右表中返回所有的值,即使左表中没有匹配(还是返回NULL) |
-- ============================== 连表查询(Join) ======================================= /*思路: 1. 分析需求,分析查询的字段来自哪些表 2. 确定使用哪种连接(7种之一) 3. 确定交叉点(两个表之间的共同列数据) 4. 判断的条件 :学生信息表中的id = 学生分数表中的s_id 条件语法有两个: 1. Join (连接的表)on (判断条件) 固定语法 --连接查询 2. Where --等值查询 */ -- 双表查询(学号,姓名,分数编号,分数) -- 这里用的Inner Join查询(也可以使用另外两种,不同点就是基于哪张表而已) SELECT si.`id`,`name`,ss.`id`,`score` FROM `student_information` si INNER JOIN `student_score` ss ON si.`id` = ss.`s_id` -- 三表查询(学号,姓名,科目名称,分数) /*思路: 先将查询的字段放在两张表查,查出来再加上下一张表的字段, 一层一层往下走。 */ SELECT si.`id`,`name`,`major_source`,`score` FROM `student_information` AS si INNER JOIN `student_score` AS sc ON si.`id` = sc.`s_id` INNER JOIN `student_source` AS so ON sc.`so_id` = so.`id`
自连接
父类:
categoryid | categoryName |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
子类:
pid | categoryid | categoryName |
---|---|---|
3 | 4 | 数据库 |
3 | 6 | web开发 |
5 | 7 | ps技术 |
2 | 8 | 办公信息 |
查询父类对应的子类关系:
父类 | 子类 |
---|---|
信息技术 | 办公信息 |
软件开发 | 数据库,web开发 |
美术设计 | ps技术 |
-- ================== 自连接查询 =======================
-- 方式一 (Where)
SELECT a.`categoryName` AS 父项,b.`categoryName` AS 子项
FROM `category` a,`category` b
WHERE a.`categoryid` = b.`pid`
-- 方式二 (Inner Join),不可以用Left/Right Join
SELECT a.`categoryName` AS 父项,b.`categoryName` AS 子项
FROM `category` a
INNER JOIN `category` b
ON a.`categoryid` = b.`pid`
排序 语法 :ORDER BY 列数据 ASC / DESC
-- 排序 : 升序 ASC,降序 DESC
-- 语法 :ORDER BY 列数据 ASC/DESC
-- 根据成绩结果排序(降序)
SELECT `sin`.`id`,`name`,`major_source`,`score`
FROM `student_information` `sin`
INNER JOIN `student_score` `ssc`
ON `sin`.id = `ssc`.`s_id`
INNER JOIN `student_source` `sso`
ON `ssc`.`so_id` = `sso`.`id`
ORDER BY `score` DESC
分页 语法 :LIMIT 数据起始下标 pageSize
/* 假设有100万条数据,为何要进行分页? 1. 缓解数据库压力 2. 给人更好的体验 也有不分页的,叫瀑布流 如:百度搜图片,刷抖音,刷快手(划到最下面,会自动加载) */ -- 每页只显示三条数据 -- 语法 :LIMIT 数据起始下标, 页面大小 SELECT `sin`.`id`,`name`,`major_source`,`score` FROM `student_information` `sin` INNER JOIN `student_score` `ssc` ON `sin`.id = `ssc`.`s_id` INNER JOIN `student_source` `sso` ON `ssc`.`so_id` = `sso`.`id` ORDER BY `sin`.`id` DESC -- ORDER BY `score` DESC LIMIT 0,3 -- 第一页 limit 0,3 (1-1)*3 -- 第二页 limit 3,3 (2-1)*3 -- 第三页 limit 6,3 (3-1)*3 -- 第四页 limit 9,3 (4-1)*3 -- 第n页 (n-1)*pageSize -- 【pageSize :页面大小】 -- 【(n-1)*pageSize : 起始下标】 -- 【n :当前页数】 -- 【总页数(pageCount) = 数据总量(dataTotal) / 页面大小(pageSize)】
练习:
-- 查询查询英语成绩排名前二的,并且分数大于80的
SELECT `sin`.`id`,`name`,`score`
FROM `student_information` `sin`
INNER JOIN `student_score` `ssc`
ON `sin`.`id` = `ssc`.`s_id`
WHERE `so_id` = 43213 AND `score`>=80
ORDER BY `score` DESC
LIMIT 0,2
-- 第二种方式
SELECT `sin`.`id`,`name`,`score`
FROM `student_information` `sin`, `student_score` `ssc`
WHERE `sin`.`id` = `ssc`.`s_id` AND `so_id` = 43213 AND `score`>=80
ORDER BY `score` DESC
LIMIT 0,2
where ( 这里再嵌套一个SQL语句 )
本质 :在where中嵌套一个查询语句
-- 查询英语成绩,并且分数大于80的 -- 方式一 SELECT `sin`.`id`,`name` FROM `student_information` `sin` RIGHT JOIN `student_score` `ssc` ON `sin`.`id` = `ssc`.`s_id` WHERE `score`>=80 AND `so_id` = ( SELECT `id` FROM `student_source` WHERE `major_source` = '英语' ); -- 方式二 SELECT `id`,`name` FROM `student_information` WHERE `id` IN ( SELECT `s_id` FROM `student_score` WHERE `score`>=80 AND `so_id` = ( SELECT `id` FROM `student_source` WHERE `major_source` = '英语' ) );
-- 查询不同课程的平均分,最高分,最低分,平均分大于80
SELECT `major_source`,AVG(`score`) AS 平均分,MAX(`score`) AS 最高分,MIN(`score`) AS 最低分
FROM `student_score` `ssc`
INNER JOIN `student_source` `sso`
ON `sso`.`id` = `ssc`.`so_id`
GROUP BY `major_source` -- 通过什么来分组
HAVING 平均分>=80 -- 分组后的过滤条件
官网:https://dev.mysql.com/doc/refman/8.0/en/func-op-summary-ref.html
-- ============== 常用函数 ============== -- 数学 SELECT ABS(-18) -- 绝对值 SELECT CEIL(9.4) -- 向上取整 SELECT FLOOR(9.4) -- 向下取整 SELECT RAND() -- 随机值 SELECT SIGN(-2) -- 返回符号类型 0~0,-2~-1,2~1 -- 字符串函数 SELECT CHAR_LENGTH('jijiji') -- 字符串长度 SELECT CONCAT('jiji','ji') -- 拼接字符串 SELECT INSERT('jiji',2,2,'kw') -- 在指定位置插入并替换原字符串 SELECT LOWER('kAng') -- 转小写 SELECT UPPER('kang') -- 转大写 SELECT INSTR('kang','k') -- 返回第一次出现子串的索引 SELECT REPLACE('坚持就能成功','坚持','努力') -- 替换指定字符串 SELECT SUBSTR('坚持就能成功',1,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() -- 获取当前版本号
函数名称 | 描述 |
---|---|
COUNT() | 计数 |
SUM() | 求和 |
AVG() | 平均分 |
MAX() | 最大值 |
MIN() | 最小值 |
… | … |
-- ============ 聚合函数 ==========
-- COUNT() 都能够统计表中的数据(想查询一个表中有多少条记录,就用Count())
SELECT COUNT(id) FROM `student_information` -- Count(字段),会忽略所有的NULL值
SELECT COUNT(*) FROM `student_information` -- Count(*),不会忽略NULL值,本质:计算行数
SELECT COUNT(1) FROM `student_information` -- Count(1),不会忽略NULL值,本质:计算行数
SELECT SUM(score) AS 总和 FROM `student_score`
SELECT AVG(score) AS 平均分 FROM `student_score`
SELECT MAX(score) AS 最大值 FROM `student_score`
SELECT MIN(score) AS 最小值 FROM `student_score`
创建自定义函数的语法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aBHCFfiJ-1686195380855)(C:\Users\LT\AppData\Roaming\Typora\typora-user-images\image-20221013175730544.png)]
删除函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LSTJrAQP-1686195380856)(C:\Users\LT\AppData\Roaming\Typora\typora-user-images\image-20221013180023241.png)]
什么是MD5?
主要增强算法复杂度和不可逆性
MD5不可逆,具体的MD5的值是一样的
MD5破解的原理,背后有一个字典,{加密后的值,加密前的值}
-- ============ MD5测试加密 ============ CREATE TABLE `testmd5`( `id` INT NOT NULL, `name` VARCHAR(20) NOT NULL, `psd` VARCHAR(10) NOT NULL, PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8; -- 明文密码 INSERT INTO `testmd5` VALUES(1,'张三','123456'),(2,'李四','123456'),(3,'王五','123456') -- 加密 UPDATE `testmd5` SET `psd` = MD5(`psd`) -- 插入的时候加密 INSERT INTO `testmd5` VALUES(4,'小明',MD5('123456')) -- 用户传进来的密码如何校验 SELECT * FROM `testmd5` WHERE `id` = 4 AND `psd` = MD5('123456')
1、事务定义
事务是一个最小的不可在分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元)。
一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。
事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。
2.事务是什么?
多个操作同时进行,那么同时成功,那么同时失败。这就是事务。
事务有四个特性:一致性、持久性、原子性、隔离性
比如有一个订单业务
1.订单表当中添加一条记录 2.商品数量数据更新(减少) 3…
当多个任务同时进行操作的时候,这些任务只能同时成功,或者同时失败。
原子性(Atomicity)
一致性(Consistency)
一致性即在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
一致性体现在两个层面:
数据库机制层面
数据库层面的一致性是,在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,Check约束 等)和触发器设置.这一点是由SQL SERVER进行保证的.
业务层面
对于业务层面来说,一致性是保持业务的一致性.这个业务一致性需要由开发人员进行保证.很多业务方面的一致性可以 通过转移到数据库机制层面进行保证.比如,产品只有两个型号,则可以转移到使用CHECK约束使某一列必须只能存 这两个型号.
隔离性(Isolation)
持久性(Durability)
隔离性导致的一些问题
脏读:(读未提交)
指一个事务读取到了另一个事务未提交的数据。
不可重复读:(读已提交)
对于事务A多次读取同一个数据时,由于其他是事务也在访问这个数据,进行修改且提交,对于事务A,读取同一个数据时,有可能导致数据不一致,叫不可重复读。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wd7NOUF1-1686195380856)(C:\Users\kang\AppData\Roaming\Typora\typora-user-images\image-20221013145104684.png)]
幻读:
执行
-- ============================== 事务 ================================= -- MySQL是默认开启事务自动提交的 SET COMMIT = 0 -- 关闭 SET COMMIT = 1 -- 开启 -- 手动处理事务 SET COMMIT = 0 -- 关闭自动提交 START TRANSACTION -- 标记一个事务的开启,往后的sql语句都在同一个事务内 INSERT xxx INSERT xxx COMMIT -- 提交:持久化(成功!) ROLLBACK -- 回滚:回到原来的地方(失败) -- COMMIT 或 ROLLBACK 执行后,事务会被自动关闭 -- 保留点 SAVEPOINT (在SQL代码中保留点名越多越好,这样就可以灵活回滚) SAVEPOINT 保留点名 -- 在此处定义保留点名 ROLLBACK TO 定义的保留点名 -- 回滚到定义的保留点名
模拟事务
-- 在shop库下建立account表,并插入数据 CREATE DATABASE `shop` USE `shop` CREATE TABLE `account`( `id` INT NOT NULL AUTO_INCREMENT COMMENT '账户标识', `name` VARCHAR(30) NOT NULL COMMENT '账户名字', `money` DECIMAL(10,2) NOT NULL COMMENT '账户余额', PRIMARY KEY (`id`) )ENGINE = INNODB DEFAULT CHARSET = utf8; INSERT INTO `account` (`name`,`money`) VALUES ('A','5000.00'),('B','10000.00'); -- =================模拟转账(事务)===================== SET autocommit = 0; -- 关闭自动提交 SHOW autocommit START TRANSACTION; -- 开始一个事务 UPDATE `account` SET `money` = `money` - 2200 WHERE `name` = 'A';-- A减2200 UPDATE `account` SET `money` = `money` + 2200 WHERE `name` = 'B';-- B加2200 COMMIT; -- 提交事务 ROLLBACK; -- 回滚事务 SET autocommit = 1; -- 恢复自动提交
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
提取句子主干,就可以得到索引的本质:索引是数据结构。
在一个表中,主键索引只能有一个,唯一索引可以有多个。
基础语法:
-- 显示所有的索引信息
SHOW INDEX FROM student_information;
-- 给指定的列增加一个全文索引
ALTER TABLE `student_information` ADD FULLTEXT INDEX `name` (`name`);
-- EXPLAIN 分析SQL语句执行的状况
EXPLAIN SELECT * FROM `student_information` WHERE MATCH(`name`) AGAINST('康');
模拟测试
-- 使用自定义函数插入100万条数据
DELIMITER $$ -- 将命令执行符;修改为$$
CREATE FUNCTION create_data()
RETURNS INT
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i<num DO
INSERT INTO `student_information`(`name`,`age`,`favorite`,`detail`,`pwd`) VALUES (CONCAT('用户',i),CEIL(RAND()*50),'学编程','健康',UUID());
SET i = i + 1;
END WHILE;
RETURN i;
END
SELECT create_data()
-- 添加索引的语法:CREATE INDEX 索引名 ON 表名(字段)
-- 没有索引
SELECT * FROM `student_information` WHERE `name` = '用户9999' -- 执行4.523 sec
-- 给name增加索引
CREATE INDEX id_student_information_name ON `student_information`(`name`)
-- 有索引
SELECT * FROM `student_information` WHERE `name` = '用户9999' -- 执行0.347 sec
索引在数据量小的时候,区别不大,在大数据时候,区别十分明显~
索引的数据结构
通常默认的数据类型为Hash
但INNODB默认的数据类型为BTREE
为什么使用视图?
语法:
CREATE VIEW 创建视图
SHOW CREATE VIEW view_name; 查询创建的视图
DROP VIEW view_name; 删除视图
CREATE OR REPLACE VIEW; 更新视图
-- 在男性用户里,查询年龄为34,26,45的用户 -- 先创建一个只有男性用户的视图 CREATE VIEW male_account AS SELECT `name` FROM `student_information` WHERE `sex` = '男'; -- 在创建的视图里查询年龄为34,26,45的用户 SELECT si.`name` FROM male_account `ma` INNER JOIN `student_information` `si` ON `si`.`name` = `ma`.`name` WHERE si.`age` IN (34,26,45) -- 刚刚创建视图没有添加age字段,现修改重来 CREATE VIEW `male_account2` AS SELECT `name`,`age` FROM `student_information` WHERE `sex` = '男'; SELECT * FROM `male_account2` -- 查看视图 DROP VIEW `male_account2` -- 删除视图 -- 在创建的视图里查询年龄为34,26,45的用户 SELECT `name`,`age` FROM `male_account2` WHERE `age` IN (34,26,45)
常见的规则:
为什么要使用存储过程?
优点:
这一点得延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。
这一点的延伸就是安全性。通过存储过程限制对基础局的访问减少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。
换句话说,使用存储过程有3个主要的好处,即简单、安全、高性能。显然,他们都很重要。
缺点:
尽管有缺陷,存储过程还是非常有用的,并且应该尽可能地使用它。
语法:
– 创建存储过程
CREATE PROCEDURE name(
IN argument1, IN(传递给存储过程)
OUT argument2, OUT(从存储过程传出,返回给调用者)
… …
)
[BEGIN
SELECT … … FROM … … INTO …; INTO (将计算得到的值保存到相应的变量)
… …
END];
– 执行存储过程
CALL name(@argument1, 所有MySQL变量名必须以@
@argument2);
DROP PROCEDURE name; – 删除存储过程
显示创建的存储过程
SHOW PROCEDURE name;
显示所有存储过程的详细信息
SHOW PROCEDURE STATUS;
DELIMITER // CREATE PROCEDURE count_age( OUT min_age INT, OUT max_age INT, OUT avg_age INT ) BEGIN SELECT MIN(age) FROM `student_information` INTO min_age; SELECT MAX(age) FROM `student_information` INTO max_age; SELECT AVG(age) FROM `student_information` INTO avg_age; END// DELIMITER ; CALL count_age(@min,@max,@avg); DROP PROCEDURE count_age; SELECT @min,@max,@avg;
在MySQL中,游标只能用于存储过程(和函数)。
使用游标的步骤:
创建游标
CREATE PROCEDURE name()
BIGIN
DELCARE 游标名称 CURSOR
FOR
SELECT … …; 要检索的语句
END;
打开,关闭游标
OPEN 游标名称;
CLOSE 游标名称;(如果不关闭,MySQL将会在END语句执行时关闭它)
从使用游标检索的数据中,取数据
FETCH 游标名称
尽量保持每个数据库的触发器名唯一!
创建触发器
CREATE TRIGGER 触发器名称 AFTER ( BEFORE ) INSERT ( DELETE、UPDATE ) ON 表名
FOR EACH ROW 【SELECT … … 触发器激活后要执行的语句】
删除触发器
DROP TRIGGER 触发器名称;
触发器仅支持表( 视图和临时表都不行 )!!!
…
)
[BEGIN
SELECT … … FROM … … INTO …; INTO (将计算得到的值保存到相应的变量)
… …
END];
– 执行存储过程
CALL name(@argument1, 所有MySQL变量名必须以@
@argument2);
DROP PROCEDURE name; – 删除存储过程
显示创建的存储过程
SHOW PROCEDURE name;
显示所有存储过程的详细信息
SHOW PROCEDURE STATUS;
DELIMITER // CREATE PROCEDURE count_age( OUT min_age INT, OUT max_age INT, OUT avg_age INT ) BEGIN SELECT MIN(age) FROM `student_information` INTO min_age; SELECT MAX(age) FROM `student_information` INTO max_age; SELECT AVG(age) FROM `student_information` INTO avg_age; END// DELIMITER ; CALL count_age(@min,@max,@avg); DROP PROCEDURE count_age; SELECT @min,@max,@avg;
在MySQL中,游标只能用于存储过程(和函数)。
使用游标的步骤:
创建游标
CREATE PROCEDURE name()
BIGIN
DELCARE 游标名称 CURSOR
FOR
SELECT … …; 要检索的语句
END;
打开,关闭游标
OPEN 游标名称;
CLOSE 游标名称;(如果不关闭,MySQL将会在END语句执行时关闭它)
从使用游标检索的数据中,取数据
FETCH 游标名称
尽量保持每个数据库的触发器名唯一!
创建触发器
CREATE TRIGGER 触发器名称 AFTER ( BEFORE ) INSERT ( DELETE、UPDATE ) ON 表名
FOR EACH ROW 【SELECT … … 触发器激活后要执行的语句】
删除触发器
DROP TRIGGER 触发器名称;
触发器仅支持表( 视图和临时表都不行 )!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。