文章目录
- 前言
- 一、基本的命令行操作
- 二、操作数据库语句
- 三、列的数据类型
-
- [3.1 字符串](#3.1 字符串)
- [3.2 数值](#3.2 数值)
- [3.3 时间日期](#3.3 时间日期)
- [3.4 空](#3.4 空)
- [3.5 int 和 varchar问题总结:](#3.5 int 和 varchar问题总结:)
- 四、字段属性
-
- [4.1 UnSigned](#4.1 UnSigned)
- [4.2 ZEROFILL](#4.2 ZEROFILL)
- [4.3 Auto_InCrement](#4.3 Auto_InCrement)
- [4.4 NULL 和 NOT NULL](#4.4 NULL 和 NOT NULL)
- [4.5 DEFAULT](#4.5 DEFAULT)
- [4.6 测试](#4.6 测试)
- [4.7 补充](#4.7 补充)
- [4.8 linux 查看表文件 补充](#4.8 linux 查看表文件 补充)
- [4.9 修改和删除表字段](#4.9 修改和删除表字段)
-
- [4.9.1 ==修改表 ( ALTER TABLE )==](#4.9.1 ==修改表 ( ALTER TABLE )==)
- 4.9.2**删除数据表**
- [4.9.3 其它](#4.9.3 其它)
- [4.10 数据库级别的外键](#4.10 数据库级别的外键)
-
- [4.10.1 建表时指定外键约束](#4.10.1 建表时指定外键约束)
- [4.10.2 建表后修改](#4.10.2 建表后修改)
- [4.10.3 删除外键](#4.10.3 删除外键)
- 五、MYSQL数据管理(重点)
-
- [5.1 DML语言](#5.1 DML语言)
-
- [5.1.1 Insert](#5.1.1 Insert)
- [5.1.2 update](#5.1.2 update)
- [5.1.3 DELETE](#5.1.3 DELETE)
-
- [delete与truncate 的区分](#delete与truncate 的区分)
- [5.2 DQL(重点,查询语句)](#5.2 DQL(重点,查询语句))
-
- [5.2.1 SELECT语法:](#5.2.1 SELECT语法:)
- [5.2.2 指定查询字段](#5.2.2 指定查询字段)
- [5.2.3 DISTINCT 去重](#5.2.3 DISTINCT 去重)
- [5.2.4 使用表达式的列](#5.2.4 使用表达式的列)
- [5.2.5 where 字句](#5.2.5 where 字句)
-
- [5.2.5.1 逻辑操作符](#5.2.5.1 逻辑操作符)
- [5.2.2.1 模糊查询](#5.2.2.1 模糊查询)
- [5.2.6 连接查询](#5.2.6 连接查询)
-
- [5.2.6.1 JOIN对比](#5.2.6.1 JOIN对比)
- [5.2.6.2 自连接](#5.2.6.2 自连接)
- [5.2.7 排序](#5.2.7 排序)
- [5.2.8 分页](#5.2.8 分页)
- [5.2.9 子查询 嵌套查询](#5.2.9 子查询 嵌套查询)
- [5.2.10 MYSQL常用函数](#5.2.10 MYSQL常用函数)
- [5.2.11 聚合函数以及分组过滤](#5.2.11 聚合函数以及分组过滤)
- [5.2.12 补充知识 MD5加密](#5.2.12 补充知识 MD5加密)
- [5.2.13 select 执行顺序](#5.2.13 select 执行顺序)
前言
数据库无非三个大类:
①操作数据库 ②操作数据库中的表 ③操作数据库表中的信息
一、基本的命令行操作
查看有哪写数据库
show databases;
使用那个数据库
use databasename
显示所有的表
show tables;
显示具体表的结构
desc tablename
describe tablename
二、操作数据库语句
SQL语句不区分大小写,SQL语句记得以分号结尾;
2.1、创建数据库
例:创建一个school数据库
CREATE DATABASE [IF NOT EXISTS] school;
2.2、删除数据库
例:删除school 数据库
DROP DATABASE [IF EXISTS] school;
2.3、使用数据库
使用school 数据库
USE school;
2.4 查看所有数据库
show DATABASES;
三、列的数据类型
3.1 字符串
char | 字符串固定大小 0-255 |
---|---|
varchar | 可变字符串 0-65535 常用的变量 String |
tinytext | 最大长度为255个字符,占用1个字节的存储空间 |
text | 保存文本 最大长度为65,535个字符,占用2个字节的存储空间 |
3.2 数值
tinyint | 1个字节 |
---|---|
smallint | 2个字节 |
mediumint | 3个字节 |
int | 4个字节 |
float | 单精度浮点类型 4个字节 |
double | 双精度浮点类型 8个字节 |
decimal | 字符串的浮点类型,可以精准计算 |
3.3 时间日期
data | YYYY-MM-DD |
---|---|
time | HH:mm:ss |
datatime | YYYY-MM-DD HH:mm:ss |
timestamp | 时间戳,从1970.1.1到现在的毫秒数 |
3.4 空
NULL 未知,注意:不要使用null进行运算
3.5 int 和 varchar问题总结:
在mysql中 int(M) M这里是宽度,并不是说int(1)就是只能写一位数字。这里是为了填充的,比如int(3),你写了一个1,最后就是001.
而varchar(3),那确实就是3个,不论你是3个字母还是3个汉字。
四、字段属性
4.1 UnSigned
无符号的
声明该数据列不允许负数 .
4.2 ZEROFILL
0填充的
不足位数的用0来填充 , 如int(3),5则为005
4.3 Auto_InCrement
自动增长的 , 每添加一条数据 , 自动在上一个记录数上加 1(默认)
通常用于设置主键 , 且为整数类型
可定义起始值和步长
当前表设置步长(AUTO_INCREMENT=100) : 只影响当前表
SET @@auto_increment_increment=5 ; 影响所有使用自增的表(全局)
4.4 NULL 和 NOT NULL
默认为NULL , 即没有插入该列的数值
如果设置为NOT NULL , 则该列必须有值
4.5 DEFAULT
默认的
用于设置默认值
例如,性别字段,默认为"男" , 否则为 "女" ; 若无指定该列的值 , 则默认值为"男"的值
4.6 测试
创建一个student表
id为主键
注意:
对于表的字段和表名尽量使用``引起来,这个符号是电脑tab上边的点,而不是单引号。
对于字符串,可以用单引号,也可以用双引号,()括号要使用英文的括号。
注释要使用英文的单引号,不同的属性要用空格符隔开。
每一行最后要加英文逗号,
bash
CREATE TABLE IF NOT EXISTS `student`(
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(10) NOT NULL DEFAULT '123456' COMMENT '密码',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`address` VARCHAR(100) DEFAULT NULL COMMENT '住址',
`email` VARCHAR(20) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
格式:
CREATE TABLE [IF NOT EXISTS] 表名
(
列名
列数据类型 [属性] [索引] [注释],
列名
列数据类型 [属性] [索引] [注释],
列名
列数据类型 [属性] [索引] [注释],
primary key(主键列名
)
)[表类型] [字符集类型] [注释]
4.7 补充
SHOW CREATE TABLE student --逆向查看构建表 student的过程(语句)
SHOW CREATE DATABASE mytext --逆向查看构建数据库 mytext的过程(语句)
DESC student --查看表结构
4.8 linux 查看表文件 补充
mysql的数据都在 data文件夹下
在linux中 我们如何知道data文件夹在哪里呢?
首先 我们可以先查看mysql的配置文件 my.cnf
find / -name "my.cnf"
如果有多个的话 选择其中一个进行查看可以
vim /etc/my.cnf之后在文件夹下 找datadir 关键字
就可以找到 data目录了
表类型:引擎
MySQL的数据表的类型 : MyISAM , InnoDB , HEAP , BOB , CSV等...
常见的 MyISAM 与 InnoDB 类型:
经验 ( 适用场合 ) :
适用 MyISAM : 节约空间及相应速度
适用 InnoDB : 安全性 , 事务处理及多用户操作数据表
数据表的存储位置
MySQL数据表以文件方式存放在磁盘中
包括表文件 , 数据文件 , 以及数据库的选项文件
位置 : Mysql安装目录\data\下存放数据表 . 目录名对应数据库名 , 该目录下文件名对应数据表 .
注意 :
-
. frm -- 表结构定义文件
-
. MYD -- 数据文件 ( data )
-
. MYI -- 索引文件 ( index )
*InnoDB类型数据表只有一个 .frm文件 , 以及上一级目录的ibdata1文件
MyISAM类型数据表对应三个文件 :
4.9 修改和删除表字段
4.9.1 修改表 ( ALTER TABLE )
修改表名 :ALTER TABLE 旧表名 RENAME AS 新表名
添加字段 : ALTER TABLE 表名 ADD字段名 列属性[属性]
修改字段 :
ALTER TABLE 表名 MODIFY 字段名 列类型[属性] --> 修改列属性
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性] -->重命名
删除字段 : ALTER TABLE 表名 DROP 字段名
4.9.2删除数据表
语法:DROP TABLE [IF EXISTS] 表名
IF EXISTS为可选 , 判断是否存在该数据表
如删除不存在的数据表会抛出错误
4.9.3 其它
-
可用反引号(`)为标识符(库名、表名、字段名、索引、别名)包裹,以避免与关键字重名!中文也可以作为标识符!
-
每个库目录存在一个保存当前数据库的选项文件db.opt。
-
注释:
单行注释 # 注释内容
多行注释 /* 注释内容 */
单行注释 -- 注释内容 (标准SQL注释风格,要求双破折号后加一空格符(空格、TAB、换行等))
-
模式通配符:
_ 任意单个字符
% 任意多个字符,甚至包括零字符
单引号需要进行转义 '
-
CMD命令行内的语句结束符可以为 ";", "\G", "\g",仅影响显示结果。其他地方还是用分号结束。delimiter 可修改当前对话的语句结束符。
-
SQL对大小写不敏感 (关键字)
-
清除已有语句:\c
4.10 数据库级别的外键
对于外键,一般我们都不会去添加物理级别即数据库级别的外键,因为这种会导致耦合性太强,容易出现错误,一般我们如果我们想使用多张表,想使用外键,都会通过程序来实现,而不是这种数据库级别的外键
4.10.1 建表时指定外键约束
bash
-- 创建外键的方式一 : 创建子表同时创建外键
-- 年级表 (id\年级名称)
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` (
`studentno` INT(4) NOT NULL COMMENT '学号',
`studentname` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`sex` TINYINT(1) DEFAULT '1' COMMENT '性别',
`gradeid` INT(10) DEFAULT NULL COMMENT '年级',
`phoneNum` VARCHAR(50) NOT NULL COMMENT '手机',
`address` VARCHAR(255) DEFAULT NULL COMMENT '地址',
`borndate` DATETIME DEFAULT NULL COMMENT '生日',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
`idCard` VARCHAR(18) DEFAULT NULL COMMENT '身份证号',
PRIMARY KEY (`studentno`),
KEY `FK_gradeid` (`gradeid`),
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
4.10.2 建表后修改
bash
-- 创建外键方式二 : 创建子表完毕后,修改子表添加外键
ALTER TABLE `student`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`);
4.10.3 删除外键
注意 : 删除具有主外键关系的表时 , 要先删子表 , 后删主表
-- 删除外键
ALTER TABLE student DROP FOREIGN KEY FK_gradeid;
-- 发现执行完上面的,索引还在,所以还要删除索引
-- 注:这个索引是建立外键的时候默认生成的
ALTER TABLE student DROP INDEX FK_gradeid;
五、MYSQL数据管理(重点)
5.1 DML语言
数据库管理语言
5.1.1 Insert
语法:
可以同时插入多条数据
INSERT INTO
表名
(字段1
,字段2
,...
) VALUES(值1
,'值2',...
),(值1
,...
),...
表名后边也可以不加字段名,但是如果不加字段名,就注意要一一匹配了,包括自增主键,自己也要写上。
例如:
往student 表中添加name和password两个字段,且同时添加上了两条数据
INSERT INTO
student
(name
,password
) VALUES('jiang','123456'),('long','123456');注意:这种只增加几个字段,而不是全部字段的,其它字段要么设置允许为空,要么有默认值,或者是主键可以自增,否则会报错。
5.1.2 update
语法:
UPDATE
表名
SET column_name1='value'[,column_name2='value'] [WHERE 条件]
例如:
UPDATE
student
SET NAME='崔',password
='123' WHERE PASSWORD='123456' AND id=5
注意
修改的属性可以有多个,但是要用英文逗号隔开。
如果不加条件 就会修改全部行。
条件也可以有多个 用 and 或者 or连接。
5.1.3 DELETE
语法:
delete from table_name [where 条件]
delete from table_name 不加条件的话 就是删除所有表内容 但不会删除表结构
TRUNCATE TABLE 表名
delete与truncate 的区分
1、相同点:都会删除表内容,但不会删除表结构
2、不同点:
delete:删除表内容之后,对于自增序列,不会清零,仍从上次自增序列开始。
truncate:对于自增序列,计数器会清零,从1开始。
以下关于delete的了解即可:
- 同样使用DELETE清空不同引擎的数据库表数据.重启数据库服务后
-- InnoDB : 自增列从初始值重新开始 (因为是存储在内存中,断电即失)
-- MyISAM : 自增列依然从上一个自增数据基础上开始 (存在文件中,不会丢失)
5.2 DQL(重点,查询语句)
5.2.1 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_count | row_countOFFSET offset}];
-- 指定查询的记录从哪条至哪条
SELECT * FROM
student
SELECT
loginpwd
,studentname
FROMstudent
注意 : [ ] 括号代表可选的 , { }括号代表必选得
5.2.2 指定查询字段
查询所有学生
SELECT * from
student
查询特定字段 并作别名 AS 可以省略 同时也可以给表做别名SELECT
loginpwd
AS 登录密码1,studentname
AS '姓名2' FROMstudent
AS s
AS 别名AS 子句作为别名
作用:
可给数据列取一个新别名
可给表取一个新别名
可把经计算或总结的结果用另一个新名称来代替
concat拼接在每个学生姓名前都加上姓名两个字 并起了别名
SELECT CONCAT('姓名:',
studentname
) AS 新名字 FROMstudent
5.2.3 DISTINCT 去重
作用 : 去掉SELECT查询返回的记录结果中重复的记录 ( 返回所有列的值都相同 ) , 只返回一条
-- # 查看哪些同学参加了考试(学号) 去除重复项
SELECT * FROM result; -- 查看考试成绩
SELECT studentno FROM result; -- 查看哪些同学参加了考试
SELECT DISTINCT studentno FROM result; -- 了解:DISTINCT 去除重复项 , (默认是ALL)
5.2.4 使用表达式的列
数据库中的表达式: 一般由文本值 , 列值 , NULL , 函数和操作符等组成
应用场景 :
①SELECT语句返回结果列中使用
②SELECT语句中的ORDER BY , HAVING等子句中使用
③DML语句中的 where 条件语句中使用表达式
-- selcet查询中可以使用表达式
SELECT @@auto_increment_increment; -- 查询自增步长
SELECT VERSION(); -- 查询版本号
SELECT 100*3-1 AS 计算结果; -- 表达式
-- 学员考试成绩集体提分一分查看SELECT studentno,StudentResult+1 AS '提分后' FROM result;
这个加一分并不会修改原始数据库中的成绩 与update set不同
避免SQL返回结果中包含 ' . ' , ' * ' 和括号等干扰开发语言程序.
5.2.5 where 字句
5.2.5.1 逻辑操作符
查询成绩在95-100之间的学生
①SELECT
studentno
,studentresult
FROMresult
WHERE
studentresult
>=95 &&studentresult
<=100
②SELECTstudentno
,studentresult
FROMresult
WHERE
studentresult
>=95 ANDstudentresult
<=100
③SELECTstudentno
,studentresult
FROMresult
WHERE
studentresult
BETWEEN 95 AND 100
--查询除了1000号学生之外的其他学生的成绩
①SELECTstudentno
,studentresult
FROMresult
WHERE
studentno
!=1000
②SELECTstudentno
,studentresult
FROMresult
WHERE NOT
studentno
=1000
5.2.2.1 模糊查询
in是要求匹配具体数值
测试
bash
-- 模糊查询 between and \ like \ in \ null
-- =============================================
-- LIKE
-- =============================================
-- 查询姓刘的同学的学号及姓名
-- like结合使用的通配符 : % (代表0到任意个字符) _ (一个字符)
SELECT studentno,studentname FROM student
WHERE studentname LIKE '刘%';
-- 查询姓刘的同学,后面只有一个字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '刘_';
-- 查询姓刘的同学,后面只有两个字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '刘__';
-- 查询姓名中含有 嘉 字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '%嘉%';
-- 查询姓名中含有特殊字符的需要使用转义符号 '\'
-- 自定义转义符关键字: ESCAPE ':'
-- =============================================
-- IN(具体数值)
-- =============================================
-- 查询学号为1000,1001,1002的学生姓名
SELECT studentno,studentname FROM student
WHERE studentno IN (1000,1001,1002);
-- 查询地址在北京,南京,河南洛阳的学生
SELECT studentno,studentname,address FROM student
WHERE address IN ('北京','南京','河南洛阳');
-- =============================================
-- NULL 空
-- =============================================
-- 查询出生日期没有填写的同学
-- 不能直接写=NULL , 这是代表错误的 , 用 is null
SELECT studentname FROM student
WHERE BornDate IS NULL;
-- 查询出生日期填写的同学
SELECT studentname FROM student
WHERE BornDate IS NOT NULL;
-- 查询没有写家庭住址的同学(空字符串不等于null)
SELECT studentname FROM student
WHERE Address='' OR Address IS NULL;
5.2.6 连接查询
5.2.6.1 JOIN对比
JOIN 对比
一般常用的是这三种
以左表为基础,就用左连接,以右表为基础就用右连接,如果要查询两个表中的交集就用内连接。
思路:
①看我们需要的字段来自哪些表
②看这些表中交叉的部分 即我们通过什么来将表连接起来
③判断使用什么连接,看以哪个表为基础。
-- 左连接 (查询了所有同学,不考试的也会查出来)
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
LEFT JOIN result r
ON r.studentno = s.studentno
-- 查一下缺考的同学(左连接应用场景)SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
LEFT JOIN result r
ON r.studentno = s.studentno
WHERE StudentResult IS NULL
注意:
如果这里我们的studetno是result表中的学号的话,那么我们左连接就会导致student表中有学号,但是没有参加考试导致result中没有记录的学生学号为null,因为最后选择的是result表中的学号,即使左连接,这些学号也不会显示。
-- 查询参加了考试的同学信息(学号,学生姓名,科目编号,分数)-- 右连接(也可实现)
SELECT s.studentno,studentname,subjectno,StudentResult
FROM student s
RIGHT JOIN result r
ON r.studentno = s.studentno
-- 思考题:查询参加了考试的同学信息(学号,学生姓名,科目名,分数)首先需要三个表 student,subject,result,我们先两两相连
5.2.6.2 自连接
自连接
数据表与自身进行连接
需求
:从一个包含栏目ID , 栏目名称和父栏目ID的表中
查询父栏目名称和其他子栏目名称
-- 创建一个表
CREATE TABLE
category
(
categoryid
INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主题id',
pid
INT(10) NOT NULL COMMENT '父id',
categoryName
VARCHAR(50) NOT NULL COMMENT '主题名字',PRIMARY KEY (
categoryid
)) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
-- 插入数据INSERT INTO
category
(categoryid
,pid
,categoryName
)VALUES('2','1','信息技术'),
('3','1','软件开发'),
('4','3','数据库'),
('5','1','美术设计'),
('6','3','web开发'),
('7','5','ps技术'),
('8','2','办公信息');
-- 编写SQL语句,将栏目的父子关系呈现出来 (父栏目名称,子栏目名称)
-- 核心思想:把一张表看成两张一模一样的表,然后将这两张表连接查询(自连接)
SELECT a.categoryName AS '父栏目',b.categoryName AS '子栏目'
FROM category AS a,category AS b
WHERE a.
categoryid
=b.pid
-- 思考题:查询参加了考试的同学信息(学号,学生姓名,科目名,分数)SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN
subject
subON sub.subjectno = r.subjectno
-- 查询学员及所属的年级(学号,学生姓名,年级名)SELECT studentno AS 学号,studentname AS 学生姓名,gradename AS 年级名称
FROM student s
INNER JOIN grade g
ON s.
GradeId
= g.GradeID
-- 查询科目及所属的年级(科目名称,年级名称)SELECT subjectname AS 科目名称,gradename AS 年级名称
FROM SUBJECT sub
INNER JOIN grade g
ON sub.gradeid = g.gradeid
-- 查询 数据库结构-1 的所有考试结果(学号 学生姓名 科目名称 成绩)SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN
subject
subON r.subjectno = sub.subjectno
WHERE subjectname='数据库结构-1'
5.2.7 排序
语法 : ORDER BY
ORDER BY 语句用于根据指定的列对结果集进行排序。
ORDER BY 语句默认按照ASC升序对记录进行排序。
如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。
-- 查询 数据库结构-1 的所有考试结果(学号 学生姓名 科目名称 成绩)-- 按成绩降序排序
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN
subject
subON r.subjectno = sub.subjectno
WHERE subjectname='数据库结构-1'
ORDER BY StudentResult DESC
5.2.8 分页
语法 : SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
好处 : (用户体验,网络传输,查询压力)
推导:第一页 : limit 0,5
第二页 : limit 5,5
第三页 : limit 10,5
...
第N页 : limit (pageNo-1)*pageSzie,pageSzie
[pageNo:页码,pageSize:单页面显示条数]
-- 每页显示5条数据SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN
subject
subON r.subjectno = sub.subjectno
WHERE subjectname='数据库结构-1'
ORDER BY StudentResult DESC , studentno
LIMIT 0,5
-- 查询 JAVA第一学年 课程成绩前10名并且分数大于80的学生信息(学号,姓名,课程名,分数)SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN
subject
subON r.subjectno = sub.subjectno
WHERE subjectname='JAVA第一学年'
ORDER BY StudentResult DESC
LIMIT 0,10
5.2.9 子查询 嵌套查询
什么是子查询?
在查询语句中的WHERE条件子句中,又嵌套了另一个查询语句
嵌套查询可由多个子查询组成,求解的方式是由里及外;
子查询返回的结果一般都是集合,故而建议使用IN关键字;
-- 查询 高等数学-1 的所有考试结果(学号,科目编号,成绩),并且成绩降序排列
-- 方法一:使用连接查询
SELECT r.
studentno
,r.subjectno
,studentresult
FROM
result
rINNER JOIN
subject
subON sub.
subjectno
=r.subjectno
WHERE
subjectname
='高等数学-1'ORDER BY
studentresult
DESC
--使用子查询SELECT
studentno
,subjectno
,studentresult
FROM
result
WHERE
subjectno
IN(SELECT
subjectno
FROM
subject
WHERE
subjectname
='高等数学-1')
ORDER BY
studentresult
DESC
-- 查询课程为 高等数学-2 且分数不小于80分的学生的学号和姓名-- 方法一:使用连接查询
SELECT s.
studentno
,studentname
FROM student s
INNER JOIN
result
rON s.
studentno
=r.studentno
INNER JOIN
subject
subON sub.
subjectno
=r.subjectno
WHERE
subjectname
='高等数学-2' ANDstudentresult
>=80
-- 方法二:使用子查询SELECT
studentno
,studentname
FROM student
WHERE
studentno
IN(SELECT
studentno
FROM resultWHERE
studentresult
>=80 ANDsubjectno
=(SELECT
subjectno
FROMsubject
WHEREsubjectname
='高等数学-2')
)
/*练习题目:
查 C语言-1 的前5名学生的成绩信息(学号,姓名,分数)
使用子查询,查询cui同学所在的年级名称
*/
SELECT s.studentno
,studentname
,studentresult
FROM
student
sINNER JOIN
result
rON r.
studentno
=s.studentno
WHERE
subjectno
IN(SELECT
subjectno
FROMsubject
WHERE
subjectname
='C语言-1')
ORDER BY
studentresult
DESCLIMIT 0,5
SELECTgradename
FROM grade
WHERE
gradeid
=(SELECT
gradeid
FROMstudent
WHERE
studentname
='cui')
5.2.10 MYSQL常用函数
数据函数
SELECT ABS(-8); /绝对值 /
SELECT CEILING(9.4); /向上取整 /
SELECT FLOOR(9.4); /向下取整 /
SELECT RAND(); /随机数,返回一个0-1之间的随机数 /
SELECT SIGN(0); /符号函数: 负数返回-1,正数返回1,0返回0/
字符串函数
SELECT CHAR_LENGTH('狂神说坚持就能成功'); /返回字符串包含的字符数 /
SELECT CONCAT('我','爱','程序'); /合并字符串,参数可以有多个 /
SELECT INSERT('我爱编程helloworld',1,2,'超级热爱'); /替换字符串,从某个位置开始替换某个长度 /
index从1开始
insert
(str,pos,len,new_str) 如果len为0就是插入
上述例子是 从1开始 替换2个 所以就把我爱这两个变为了超级热爱SELECT LOWER('KuangShen'); /小写 /
SELECT UPPER('KuangShen'); /大写 /
SELECT LEFT('hello,world',5); /从左边截取 /
SELECT RIGHT('hello,world',5); /从右边截取 /
SELECT REPLACE('狂神说坚持就能成功','坚持','努力'); /替换字符串 /
SELECT SUBSTR('狂神说坚持就能成功',4,6); /截取字符串,开始和长度 /
SELECT REVERSE('狂神说坚持就能成功'); /*反转
-- 查询姓周的同学,改成邹
SELECT REPLACE(studentname,'周','邹') AS 新名字
FROM student WHERE studentname LIKE '周%';
日期和函数
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 VERSION(); /版本 /
SELECT USER(); /用户/
5.2.11 聚合函数以及分组过滤
函数名称 描述
COUNT() 返回满足Select条件的记录总和数,如 select count(*) 【不建议使用 ,效率低】
SUM() 返回数字字段或表达式列作统计,返回一列的总和。
AVG() 通常为数值字段或表达列作统计,返回一列的平均值
MAX() 可以为数值字段,字符字段或表达式列作统计,返回最大的值。
MIN() 可以为数值字段,字符字段或表达式列作统计,返回最小的值。
-- 聚合函数
/COUNT:非空的 /
SELECT COUNT(studentname) FROM student;
SELECT COUNT( ) FROM student;SELECT COUNT(1) FROM student; /推荐/
-- 从含义上讲,count(1) 与 count() 都表示对全部数据行的查询。
-- count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。
-- count( ) 包括了所有的列,相当于行数,在统计结果的时候,包含字段为null 的记录;-- count(1) 用1代表代码行,在统计结果的时候,包含字段为null 的记录 。
/*
很多人认为count(1)执行的效率会比count()高,原因是count()会存在全表扫描,而count(1)可以针对一个字段进行查询。其实不然,count(1)和count(*)都会对全表进行扫描,统计所有记录的条数,包括那些为null的记录,因此,它们的效率可以说是相差无几。而count(字段)则与前两者不同,它会统计该字段不为null的记录条数。
下面它们之间的一些对比:
1)在表没有主键时,count(1)比count()快
2)有主键时,主键作为计算条件,count(主键)效率最高;
3)若表格只有一个字段,则count( )效率较高。
*/
SELECT SUM(StudentResult) AS 总和 FROM result;
SELECT AVG(StudentResult) AS 平均分 FROM result;
SELECT MAX(StudentResult) AS 最高分 FROM result;
SELECT MIN(StudentResult) AS 最低分 FROM result;
题目:
-- 查询不同课程的平均分,最高分,最低分
-- 前提:根据不同的课程进行分组
SELECT subjectname,AVG(studentresult) AS 平均分,MAX(StudentResult) AS 最高分,MIN(StudentResult) AS 最低分FROM result AS r
INNER JOIN
subject
AS sON r.subjectno = s.subjectno
GROUP BY r.subjectno
HAVING 平均分>80;
注意:
where写在group by前面.
要是放在分组后面的筛选
要使用HAVING...
因为having是从前面筛选的字段再筛选,而where是从数据表中的>字段直接进行的筛选的
*/
5.2.12 补充知识 MD5加密
一、MD5简介
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
二、实现数据加密
新建一个表 testmd5
CREATE TABLE
testmd5
(
id
INT(4) NOT NULL,
name
VARCHAR(20) NOT NULL,
pwd
VARCHAR(50) NOT NULL,PRIMARY KEY (
id
)) ENGINE=INNODB DEFAULT CHARSET=utf8
插入一些数据
INSERT INTO testmd5 VALUES(1,'kuangshen','123456'),(2,'qinjiang','456789')
如果我们要对pwd这一列数据进行加密,语法是:
update testmd5 set pwd = md5(pwd);
如果单独对某个用户(如kuangshen)的密码加密:
INSERT INTO testmd5 VALUES(3,'kuangshen2','123456')
update testmd5 set pwd = md5(pwd) where name = 'kuangshen2';
插入新的数据自动加密
INSERT INTO testmd5 VALUES(4,'kuangshen3',md5('123456'));
查询登录用户信息(md5对比使用,查看用户输入加密后的密码进行比对)
SELECT * FROM testmd5 WHERE
name
='kuangshen' AND pwd=MD5('123456');
5.2.13 select 执行顺序
我们先执行from,join来确定表之间的连接关系,得到初步的数据
where对数据进行普通的初步的筛选
group by 分组
各组分别执行having中的普通筛选或者聚合函数筛选。
然后把再根据我们要的数据进行select,可以是普通字段查询也可以是获取聚合函数的查询结果,如果是集合函数,select的查询结果会新增一条字段
将查询结果去重distinct
最后合并各组的查询结果,按照order by的条件进行排序