MySQL 查询

MySQL 单表多表查询

select 字段名 from 表名 where 条件

例如:select id from user where name='张三'

​ 查询出 user表中 name为张三 的id

条件查询关键字

= 等于
<> 或 != 不等于
>、 < 、>= 、<=  大于、小于、大于等于、小于等于

between ... and .... 两个值之间,但前值必须小于后值

is null 和 is not null  判断空的

and 并且  , or 或者

in 包含 例如 in('a','b');

not 用于取非,主要用于 is 和 in

like 模糊查询 例如 username like %c% 或 username like _c%
     %匹配任意个字符 、下划线_ 匹配单个字符
其它关键字
distinct 去重 例如,select distinct dep_name from ....

desc 降序
asc  升序(默认)
order by age asc,name desc; 按年龄升序,当年龄一样时,按名字降序
例子:找出工资在1250到3000之间的员工的姓名和薪资,要求按薪资进行降序排序。

select name,sal 
from emp 
where sal between 1250 and 3000 
order by sal desc;

单行处理函数

数据处理函数又被成为单行处理函数,特点是一个输入对应一个输出。 
常见的有
lower 转小写 lower('A')
upper 转大写 lower('a')
substr 截取字符串 substr(字段名,起始位置从1开始,截取的长度)
length 取长度 
trim 去两边的空格
str_to_date 字符串转日期 ('字符串日期','日期格式')%Y %m %d %h %i分 %s秒
            str_to_date('01-10-1999','%d-%m-%Y')
            这种'1999-01-01' 正确格式无需使用函数,mysql会自动转换
date_format ('日期类型数据','日期格式') 日期转字符串 date_format(birth,'%m/%d/Y') 这函数没啥用,存正确格式的日期,mysql会自动转换
rand 生成随机数
round 四舍五入 round(1.23, 2) 保留2位小数
concat 对字符串进行拼接 concat(name1,name2)
ifnull 将null转换成一个具体指值 ifnull(age,0) ,表示如果年龄是空,用0代替

case 字段名 when 条件 then 做什么 else 做什么 end 
例子:当sex为1时,表示为男,否则表示为 女
case sex when '1' then '男' else '女' end 

多行处理函数(分组函数)

分组函数又被称为多行处理函数,特点:多个输入对应一个输出,自动忽略null的记录,不能使用在where后。
使用方式:函数名(字段名),例如 sum(score) ,表示对 分数进行求和。

常见的有 
max 取最大值
min 取最小值
avg 求平均值
sum 求和

count 计数 
    count(*)、count(字段名)和 count(1) 的区别? 

    答:(*)会计算包含null的记录,count(字段名)则忽略null的记录,使用*效率更低
        列名为主键,count(列名) 会比 count(1) 快 ;
        列名不为主键,count(1) 会比 count(列名) 快 ;
        如果表多个列并且没有主键,则 count(1) 的执行效率优于 count() ;
        如果有主键,则 select count(主键)执行效率最优;
        如果表只有一个字段,则 select count(*)最优。

分组查询(重要)

select 字段名 from 表名 where 条件 order by 字段名

SQL语句执行顺序: from → where → group by → select → order by

例子1:按照工作岗位分组,对工资进行求和,查询出岗位和工资总和
     select job,sum(sal) from emp group by job;

例子2:按照部门编号分组,找出每个部门的最高薪资
     select depno,max(sal) from emp group by depno;

例子3: 找出每个部门,不同工作岗位的最高薪资(按照部门编号分组)
     select depno,job,max(sal) from emp group by depno,job;

例子4: 找出每个部门的最高薪资大于3000的信息(按照部门编号分组)
     方式1:select depno,max(sal) from emp where sal>3000 group by depno;
     方式2:select depno,sal from emp group by depno having max(sal)>3000;
     having 可以对分完组后的数据进行再次过滤,不能单独使用,得和group by配合。
     优先使用方式1,where,效率更高

例子5:找出每个部门的平均薪资大于2500的信息(按照部门编号分组) 
     select depno,avg(sal) from emp group by depno having avg(sal)>2500;
     此例子只能用having,无法用where

备注:用了 group by后,select 后面只能跟 参与分组的字段 或 分组函数,否则无意义;

注意:使用分组函数前必须要先分组,所以不能在where 后使用分组函数,例如不能 ...where min(x);

为什么min(x) 不能用在where 的后面,因为使用min(x)的时候,还没有进行分组!请参考SQL的执行顺序。

Mysql 多表查询

内连接

等值连接

查询每个员工所在的部门名称,显示员工名和部门名

select e.ename,d.dname
from emp e
join dept d
on e.deptno = d.deptno;

非等值连接

找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级?

select e.ename,e.sal,s.grade
from emp e
join salgrade s
on e.sal between s.losal and s.hisal;

自连接

查询员工的上级领导,要求员工名和对应的领导名(同  张表)

select a.ename,b.ename
from emp a
join emp b
on a.mgr = b.empno

外连接

sql语句中的inner和outer可以省略,带有right或left的是外连接。

左外连接

select e.ename,d.dname
from dept d
 left join emp e
on e.deptno = d.deptno;

右外连接

select e.ename,d.dname
from dept d
right join emp e
on e.deptno = d.deptno;

right 代表什么,表示将join关键字右边的这张表看成主表,主要是为了将右边的这张表的数据全部查询出来,捎带着关联查询左边的表,在外连接当中,两张表连接,产生了主次关系。

三表连接

找出每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级

select e.ename,d.dname,e.sal,s.grade
from emp e
join dept d
on e.deptno = d.deptno
join salgrade s
on e.sal between s.losal and hisal;
找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名、领导名、部门名、薪资、薪资等级

select e.ename,l.ename,d.dname,e.sal,s.grade
from emp e
join dept d
on e.deptno = d.deptno
join salgrade s
on e.sal between s.losal and hisal;
left join emp l //left 保证emp表的数全部查出来
on e.mgr = l.empno

MySQL 子查询

select 中 嵌套 select语句,被嵌套的select 语句成为子查询

可嵌套的位置:select (select) from (select) where (select)

where后出现子查询

找出比最低工资高的员工姓名和工资

select ename,sal from emp where sal > (select min(sal) from emp);

from 后出现子查询

找出每个岗位的平均薪资的薪资等级

select t.*,s.grade
from (select job,avg(sal) as avgsal from emp group by job) t
join salgrade s
on t.avgsal between s.losal and s.highsal; 

select 后出现子查询

找出每个员工的部门名称,要求显示员工名,部门名(此题了解即可)

select e.ename,(select d.dname from dept d where e.deptno=d.deptno) as dname
from emp e;

此情况的子查询只能一次返回1条结果,如果结果是多条会报错,因为和其它字段结果行数不匹配

其它知识

union的例子

第1种:select ename,job from emp where job='Manager' or job='Salesman';

第2种:select ename,job from emp where in('Manager','Salesman');

第3种:
select ename,job from emp where job='Manager';
union
select ename,job from emp where job='Salesman'

第3种使用 union的效率要高一些,对于表连接来说,每连接一次新表则匹配的次数满足笛卡尔积,成倍的翻,但是union可以减少匹配的次数,还可以完成两结果的拼接。
注意,使用union 进行结果合并时,要求两语句的列数和各字段相同
limit

limit startIndex,length;

limit 5; 前5条记录
limit 2,5; 从第3条开始,往后取5条

注意:limit在order by后执行!

MySQL 笔记

启动或停止

net start mysql;
net stop mysql;

登录或退出

mysql -uroot -p123
mysql -uroot -p 这种方式可隐藏输入的密码
mysql -h IP地址或域名 -uroot1 -p 远程登录服务器的Mysql
exit 退出
\c 终止当前命令

查看信息或使用

show databases;
show tables; 
use tableName;
select * from tableName; 查看表的数据
desc tableName; 查看表的结构

查看数据库版本和当前数据库

select version();
select database();

导入sql文件和执行脚本

source C:\xx.sql

创建

创建数据库 create table tableName;

数据导出

//导出fruitshop数据库
mysqldump fruitshop > D:\xxx\xxx.sql -uroot -p123

//导出fruitshop数据库的user表
mysqldump fruitshop user > D:\xxx\xxx.sql -uroot -p123

数据导入

create database table;
source D:\.....

数据库概念理论知识

DQL:数据库查询语言 ,例如select ...

DML:数据库操作语言(对表的数据进行操作)
凡是对表当中的数据进行增删改
例如:insert增、delete删、update改

DDL:数据库定义语言(对表的结构进行操作)
凡是带有create增、drop删、alter改的搜索DDL

TCL:事务控制语言(包括事务提交commit、事务回滚rollback)

DCL:数据控制语言(授权grant、撤销权限revoke...)

表的命名和字段命名 使用下划线分隔单词,例如 table_name,user_phone

常见的数据类型

varchar 可变长度的字符串,会根据实际的数据长度分配大小,优点:节省空间,缺点:需要动态分配空间速度慢
char 定长字符串,char(6) 就是6,优点:速度较快,缺点:使用不当会导致空间浪费
int 数字中的整数型,等同于java 的int
bigint 数字中的整数型,等同于java 的long
float 单精度浮点数
double 双精度浮点数
date 短日期 只包括年月日
datetime 长日期 包括年月日时分秒
text 长文本
clob 字符大对象,最多可存4G的字符串,比如存文章
blob 二进制大对象 用于存储图片、声音、视频;需要使用IO流插入

建表 Create

create table 表名 (
    字段名1 数据类型,
    字段名2 数据类型, 
    ...);

//将查询结果 插入到一张新表中
create table 新的表名 as select * from user; 

删表 Drop

drop table 表名;

修改表 Alter

 alter table t_student rename to student;

插入数据 Insert

insert into 表名(字段名1,字段名2) values('数据1','数据2');
insert into 表名 values('数据1','数据2'); 省略字段名,等同插入所有字段
insert into 表名 values('数据1','数据2'),('数据3','数据4'); 

将查询结果插入到一张表中
insert into 插入的表名 select * from user;

修改数据 Update

update 表名 set 字段名1='数据1',字段名2='数据2' where 条件;
update user set username='test',user_emai='xx@qq.com' where id=1;

删除数据 Delete

delete 语句 删除的不是真实删除,可以支持回滚
delete from 表名 where 条件;
delete from user where id=1;

快速删除表中的数据(物理删除)
truncate 删除后不支持回滚,优点快速
truncate table 表名;

数据库范式

第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。

第二范式:建立在第一范式基础之上,要求所有的非主键字段完全依赖主键,不要产生部分依赖;

第三范式:建立在第二范式基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖;

设计数据库表的时候,按照以上的范式进行,可以避免表中数据冗余,空间的浪费;

MySQL 约束和事务

约束

什么是约束(constraint) ,在创建表的时候,我们可以给表中的字段加入一些约束,来保证表中数据的完整性、有效性。

约束包含哪些?

约束

create table user(
 id int not null unique, //如果一起使用这两,自动设为主键
 age int not null, //非空,只有列级约束
 name varcah(255) unique,//唯一
 email varchar(255),
 phone varchar(255),
 uniqe(eamil,phone) 
 //约束没有添加在列的后面,这种约束被称为表级约束,如上行
);
int id primary key auto_increment 单一主键,自动增长
primary key(id,name) 联合主键,不建议使用!
任何一张表都应该有主键,主键一般为自动增长id

外键约束
foreign key
foreigh key(uid) references user(id) 将user表的id作为外键 
外键要唯一性,才能引用

存储引擎

create table user(......)engine=引擎名 defaule charset=utf8;

InnoDB
    这是mysql默认的存储引擎,安全,同时也是个重量级的存储引擎。
    支持事务,支持数据库奔溃后自动恢复机制。
    表空间tablespace 被用于存储表的内容

---------------------------------------------------
MyISAM
    使用三个文件表示每个表
    格式文件、数据文件、索引文件
    对于一张表老说,只要是主键或者加有unique约束的字段上会自动创建索引
    特点:可被转换为压缩、只读表来节省空间,不支持事务。
----------------------------------------------------    
Memory
    内存存储引擎,数据和索引存在内存中,速度快。
    不能包含text或blob字段
    特点:查询效率最高,不安全,断电后数据消失

事务

一个事务其实就是个完整的业务逻辑(增、删、改)
事务的四大特性:

  1. 原子性: 说明事务是最小的工作单元,不可再分;
  2. 隔离性:A事务在操作一张表时,另一张表也操作这张表,具有一定的隔离性;
  3. 一致性:要么同时成功,要么同时失败;
  4. 持久性:事务提交后,将数据保存在磁盘上;

假设转账,从A账户向B账户中转账1w
将A账户的钱减去1w,将B账户的钱加上1w
这就是个完整的业务逻辑。

以上的操作是一个最小的工作单元,要么同时成功,要么同时失败。

事务是怎么做到多条DML语句同时成功和同时失败的呢?
InnoDB引擎:提供了一组用来记录事务性活动的日志文件

在事务的执行过程中,每一条DML操作都会记录到”事务性活动的日志文件“中,在提交事务过程中,我们可以提交事务,也可以回滚事务。
提交事务?
清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中
提条事务标志着,事务的借宿,并且是一种全部成功的结束。
回滚事务?
将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件。
回滚事务标志着,事务的结束,并且是一种全部失败的结束;
提交后将不可回滚;

怎么提交事务?
提交事务:commit;
回滚事务:rollback;
事务对应的英语单词是transaction

MySQL 默认的事务是自动提交方式
如果关闭mysql自动提交机制
先执行:start transaction;
再执行SQL语句,insert .....
然后 rollback; 即可回滚

  1. 事务的隔离级别:
    读未提交(read uncommitted)(没有提交就能读到):
    最低的隔离级别,事务A可以读取到事务B未提交的数据,会造成脏读;
    这重隔离级别一般没人用;

  2. 读已提交(read committed)(提交之后才能读到):
    事务A只能读取到事务B提交之后的数据,可解决脏读。
    存在缺点:不可重复读数据,在事务开启之后,第一次读到的数据是3条,当前事务还没有结束,可能第二次再读取的 时候,读到的数据是4条。
    这种隔离级别读到的数据是绝对的真实,是oracle默认的。

  3. 可重复读(repeatable read)(提交之后也读不到,读到的是刚开启事务时的数据):
    事务A开启之后,每次事务A中读取的数据都是一致的,即使事务B已修改并提交,读取到的数据还是没有改变。会出 现幻读,不够真实。
    这是MySQL默认的隔离级别;

  4. 序列化(serializable):
    最高的隔离级别,效率最低,但解决了所有问题,但不能并发,有点类似synchronized,需要排队,线程同步。

    设置全局的隔离级别
    set global transaction isolation level read uncommitted;

    查询隔离级别
    select @@tx_isolation

索引

索引是数据库表的字段上添加的,是为了提高查询效率存在的一种机制,有点像书的目录。

底层通过自平衡二叉树BTree 实现,缩小扫描的范围,避免全表扫描,

mysql中,主键上和unique字段上会自动添加索引

啥情况使用索引呢?

  1. 数据量庞大;
  2. 该字段经常出现在where的后面,已条件的形式存在,也就是说这个字段总是被扫描;
  3. 该字段很少的DML操作,因为DML后,索引要重新排序

建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低速度,建议通过主键查询或nnique字段查询

create index emp_ename_index on emp (ename);
给emp表的ename字段添加索引,起名emp_ename_index

drop index emp_ename_index on emp;删除索引

查看是否有索引
explain select * from user where ename='abc'
查看type和扫描行数rows,判断是否有索引

索引的失效?

  1. select * from user were username like '%c';
    username 即使添加了索引也不会走索引
    因为%号开始的原因,不知道开头是啥,走不了索引
  2. 使用or也会失效,要求or的两边都要有索引,索引其中有一边没,就失效了,建议使用union不会失效;
  3. 使用复合索引的时候,没有使用左侧的列查找,索引失效
    什么是复合索引?两个字段,或者更多字段联合起来添加一个索引。(a,b),使用右边的b会失效
  4. 索引的列参与了运算 例如,where sal +1 = 800,索引失效
  5. 索引列使用了函数,例如 where lower(name),索引失效

视图

创建视图对象

create view user_view as select * from user;

删除视图

drop view user_view

只有查询语句才能以view视图的形式创建

我们可以面向视图对象进行增删改查,通过对视图的操作,会影响到原表数据。
例如对视图进行查询 select * from 视图名;

视图对象在实际开发中 有什么用?

视图用来简化sql语句的,面向视图进行查询,假设有条很复杂的sql语句,每次都在不同的位置反复使用。每一次使用都需要重复编写,这时候,可以使用视图代替。

使用视图时,可以像使用表一样,视图不是在内存当中,视图对象也是存储在硬盘上,简化开发,利于维护。

JDBC-通用工具类,来看看呀 ~

介绍下我写的一个工具类,简化了日常开发中对MySQL数据库的连接和增删改查的一些繁琐操作。
   这是一个较为通用的“增删改查” 工具类,比较适用于无需使用框架开发的小项目 ,可以大大减少了开发时DAO层重复的代码,利于代码维护,分享给大家看看 。

JDBC工具类

(图片看不清的话,鼠标右键 ,点击 “在新标签页中查看图片”)

查询 方法

(增、删、改) 方法

-------------------------------------------------------------

如您感兴趣,点击下方按钮, 下载源码(文件小,仅11.6 KB

如何使用呢?

下载后,将MyJDBCUtil.java 放到项目的任意包中,在代码中调用MyJDBCUtil的静态方法即可。

下面是2个使用例子(DAO层的增、查)

备注:水平有限,暂时做不到很通用,以后我会继续完善的!有啥bug请大家指出哈哈哈!

养成编程的好习惯,真的很重要!

相信有许多同学刚接触写代码的时候

和我当初一样,主要有以下3个坏习惯

① 命名随意和不规范;
怎么简单怎么来,就图省事(比如直接用a,b,c1,c2);

② 代码不懂得模块化;
好几个实现逻辑挤在一个方法里 且 代码层级缩进不清晰;

③ 不写注释;
觉得注释不重要不想花时间写,只在意代码的功能实现;(写时很舒畅,回看很懵逼)

这些坏习惯在日常的刷题、写小Demo时,不会有什么问题,但要是在稍微完整些的项目或团队开发中,会严重影响到代码质量和效率,本人曾因为图省事,不写注释且把实现逻辑都写在一个模块里,导致后面代码很难扩展、出Bug后找了大半天、代码阅读起来很费劲等问题,这种情况,写的时候倒是爽了,但可能过几天需要对此功能进行修改的时候,就会后悔了哈哈, 注释往往花的时间很少,但改Bug花的时间可能多出好几倍 。可以说是 “ 因小失大 ,以贪小利失其大利也 ”。

在我看来,写代码时,事先应做个流程设想,最好别直接开始写,有时间可以通过笔记写出大致流程,然后随着脑海的逻辑,比如写某功能及注释,可以边写边注释,也可以每写个模块立即补上注释,这样不仅提高了代码的可读性,也可能在注释过程中发现了问题,从而减少了出bug的概率,然后每写完一个模块,也应对它进行功能测试(除非你很有自信嘻嘻)。 要有“码出质量,码出高效”的目标,除非是项目很赶时间,这些模块做了多次很熟悉了,这时候可以适当只考虑功能实现,注释等有空再补。

我再说说注释方面,我认为也不能盲目写注释,比如没必要每行代码都写注释、注释不突出重点,这样会使阅读代码时混乱,所以简单的部分无需注释,毕竟一个好的代码,从它的命名中就能见名知意啦,当然这建立在有个规范的命名习惯。

好的注释真的带给我很多便利,有次在写一个论坛类项目时,中途停止了开发,那段时间考驾照去了,期间隔了1个多月没开发,拿到驾照后我立马想继续开发这个项目,但打开后傻愣了一会,忽然之间不知从何开始了,但没过半小时,我翻了翻之前的开发笔记,伴随着代码注释看,比如找某个模块时,不需要从代码中寻找英文关键词,只需将注意力集中在显眼的绿色中文注释块,便能很快找到,或者直接搜索中文关键词,不再担心忘记英文命名的关键词。我很快就上手了,很快就衔接上了开发点;有时候我也会把代码发给同学看,分享自己的想法,他们许多人拿到代码后,也很快能看懂我代码的实现逻辑。 这让我更加认同编程中有好的注释、好的编程习惯的重要性,也能让你编程水平提升得更快;

前言说的有点多,啰嗦了哈哈......编程的好习惯很重要,要怎么培养好这个习惯呢?首先,要认识到这个不是一天两天就能养成的,刚开始肯定不适应,觉得容易乱,所以你先要坚持一段时间,将这个习惯变为真正的习惯。

下面我说说2个常见的Java编程规范(均需见名知意)


包、类、变量、方法的命名:

  • 包名全部小写;
  • 类名首字母大写,其余组成词首字母依次大写; 例如 MyTest 、UserInfo
  • 变量名和方法名,采用驼峰命名法;例如: firstName 、myCamelCase 、myMethod
  • 常量名全部大写,例如:MAX_VALUE、PASSWORD

代码注释 规范

单行注释、多行注释

类、方法、 类的属性(成员变量) 的注释必须使用 Javadoc 规范

备注:注释大致是这样,可能每个公司或团队的注释规范也会有些改动,有些不同地方,很正常。就像我的注释风格,我是按IT大厂阿里巴巴的Java开发手册中的规范来写的,但大家的理念都是 “码出质量,码出高效”。下方是阿里巴巴Java开发手册的pdf版下载链接,建议下载学习看看。

今天就码这么多字了,改天有空我会继续完善的哈,有不足之处欢迎大家提出~

分享个Github上发现的一个不错的学习网站,干货多

http://www.cyc2018.xyz/

刷题学习牛客网:https://www.nowcoder.com/intelligentTest

Java相关,经典↓ https://github.com/Snailclimb/JavaGuide

大家平时的网上学习平台或刷题的地方有哪些呢?
我推荐下我平时常逛的是: 牛客、CSDN、LeetCode、B站掘金

Java知识点总结pdf,建议下载看看 ↓ ↓ ↓