mySQL 汇总

登录MySQL

win+R 打开查询命令

输入 cmd

输入net start MySQL 打开mysql

报错 :系统错误,拒绝访问 (没权限!)
解决办法 :搜索栏查询'cmd' 使用管理员身份运行

(或鼠标右键'开始',windows powershell(管理员) )


重新打开MySQL

net start mysql

打开MySQL所在地址D:\phpstudy_pro\Extensions\MySQL8.0.12\bin

C:\Windows\system32>d:      /*跳转到安装MySQL的d盘*/

D:\>cd D:\phpstudy_pro\Extensions\MySQL8.0.12\bin    /*cd 跳转mysql安装目录下bin文件*/

D:\phpstudy_pro\Extensions\MySQL8.0.12\bin>mysql -uroot -p     /*输入MySQL账号和密码*/


报错 Can't connect to MySQL server on 'localhost' (10061)
解决办法 : 将mysql加入到window系统服务中mysqld --install



报错 Access denied for user 'root'@'localhost' (using password: YES)
解决办法 :这个提示是密码错误。。

如果忘记了密码,先关闭MySQL服务net stop mysql

跳过密码验证 mysqld --skip-grant-tables

mysql 8.0之后的版本mysqld -console --skip-grant-tables --shared-memory

重新尝试密码 成功进入MySQL


MySQL 数据库定义语言 (DDL)

查看MySQL中存在的数据库

mysql>  show databases;

注意!MySQL数据库中必须用 ";" 分开,否则MySQL默认语句未写完!


使用数据库my12

mysql> use my12;

查看my12数据库中所有表 show tables

mysql> show tables;

查看表设计结构 desc/show create table xx

mysql> desc ls;

查看表详细结构

mysql> show create table ls;

删除表 drop table if exists xx

mysql> drop table if exists ls;

创建一个表create table xx()

create table 表名(
			 列名 数据类型 [列级约束条件],
             列名 数据类型 [列级约束条件],
             ...
             列名 数据类型 [列级约束条件]);

mysql> create table t1(
    -> id int primary key not null auto_increment,
    -> name varchar(10) not null,
    -> sex enum('男','女') not null default '男');

报错原因:primary key 后面要加 not null

查看表结构 desc

mysql> desc t1;

修改表信息 alter 增(add)删(drop)改(change)

alter table 表名 
                 [add column 新列名 数据类型[列级约束条件]],
				 [drop column 列名[restrict|cascade]],
			     [change column 原列名 新列名 数据类型[列级约束条件]];

修改表名

修改表名称为t11
mysql> alter table t1 rename to t11;

新增列

  新增一个列'age', int型,非空,在'sex'列之后
mysql> alter table t1
    -> add column `age` int not null after `sex`;  

删除列

删除age列
mysql> alter table t1
    -> drop column age;

修改列名称

修改'name'列为'na1',varchar(10)为varchar(20)
mysql> alter table t1
    -> change column `name` `na1` varchar(20);

注意:修改列名的同时需要将列类型给写上,否则报错


修改列 数据类型

mysql> alter table t11 modify na1 int;

修改列排序

ALTER TABLE <表名> MODIFY <字段名> <字段数据类型> [FIRST/AFTER] <如果使用AFTER,排列在哪个字段后面,就写哪个字段的名称,FIRST就不需要了>

修改第一列 first

修改name为第一列
mysql> alter table t11 modify name varchar(10) first;

将xx放在xx后面 after

将name放在sex后面
mysql> alter table t11 modify name varchar(10) after sex;

修改存储引擎

ALTER TABLE <表名> ENGINE=<更改后的引擎> ;

首先,查看现有表的存储引擎

mysql> show create table t11;

修改表引擎为 innodb

mysql> alter table t11 engine=innodb;



数据库操纵语言 (DML)

插入数据 inster

①单行+全列插入
insert into 表名 values (xx, xx, xx, xx);
insert into 表名 values (xx, xx, xx, xx);
②多行+指定列插入
insert into 表名 (id, sn, name) values
	(xx, xx, 'xx'),
	(xx, xx, 'xx'),
	(xx, xx, 'xx');

删除数据 delete

DELETE FROM 表名 WHERE 条件;

-- 删除孙悟空的信息
delete from student where name = '孙悟空';

-- 仅删除表的全部数据 for-each
delete from student;

更新数据 update

UPDATE 表名 SET 列名=值,... WHERE 条件;

-- 修改曹孟德的数学成绩为80分,语文成绩为90分
update student set math = 80, chinese = 90 where name = '曹孟德';

-- 将总分倒数三名同学的数学成绩加上20分  (支持limit,不支持offset)
update student set math = math + 20 order by Chinese + math + english limit 3; ????

-- 将所有同学的语文成绩更新为2倍
update student set chinese = chinese * 2;

数据库查询语言(DQL)

单表查询

select   查询列名
from     表名
where    条件
group by    分组条件 
order by    desc降序,asc升序 (默认值)
having      筛选条件(优先级最低)
limit       分页数量

select

-- 全表查询,不建议使用
select * from student;
-- 指定列查询
select id, name, english from student;

-- 结果集为表达式
select id, name, (chinese + math + english) / 3 from student;
-- 自定义结果集的列名
select id, name, chinese + math + english 总分 from student;

where

-- 查询english成绩高于60分的学生
select * from student where english > 60;

-- and与or
select * from student where english > 60 and math > 60;
select * from student where english > 90 or math > 90;

-- 范围查询
select * from student where english between 80 and 100;

-- in查询
select * from student where math in (80, 85, 90, 95, 100);

-- 模糊查询 like
-- %匹配任意多个(包括0个)字符
select name from student where name like '孙%';
select name from student where name like '%孙';
select name from student where name like '%孙%';
-- _严格匹配一个任意字符
select name from student where name like '孙_';

-- NULL查询
select * from student where qq_mail is not null;
select * from student where qq_mail is null;

去重 distinct

-- 可以列出所有不重复的math成绩集合
select distinct math from student;

-- 此时就没有去重功能了,因为没有id和math同时重复的学生
select distinct id, math from student;

分组group by

GROUP BY  <字段名>[,<字段名>,<字段名>]
group by 关键字可以根据一个或多个字段对查询结果进行分组
group by 一般都会结合Mysql聚合函数来使用
如果需要指定条件来过滤分组后的结果集,需要结合 having 关键字;
where不能与聚合函数联合使用 并且 where 是在 group by 之前执行的

再次筛选 hiving

group by 后面的having是对分组后的字段进行再次过滤筛查,
此时行已经被分组。
(大部分都)使用了聚合函数。
满足HAVING 子句中条件的分组将被显示。

HAVING 不能单独使用,必须要跟 GROUP BY 一起使用
HAVING子句可包含一个或多个用AND和OR连接的谓词

WHERE 和 HAVING 也不是互相排斥的,我们可以在一个查询里面同时使用 WHERE 和 HAVING。包含分组 统计函数的条件用 HAVING,普通条件用 WHERE。这样,我们就既利用了 WHERE 条件的高效快速,又发挥了 HAVING 可以使用包含分组统计函数的查询条件的优点


窗口函数 partition by

窗口函数在使用时需要定义一个窗口(分组),然后对每一行应用窗口函数,正在计算的这行叫做"当前行"(current row)。

窗口函数与group by的区别:

在使用聚合函数的时候我们通过 group by 关键字来定义如何分组,
而窗口函数是通过 over 关键字和 partition by 关键字来定义分组
(这里的 partition by 是分组的意思,和分区表没有任何关系)
聚合函数(例如:sum/avg/min/max)会针对每个分组(窗口)聚合出一个结果(每一组返回一个结果)。
窗口函数会对每一条数据进行计算,并不会使返回的数据变少(每行在最后增添一列返回一个结果)
窗口函数会逐行计算,其重点是计算当前行与窗口内其他成员之间的关系,例如:组内排序,累积分布

聚合函数作为窗口函数使用

#查询每个人的总成绩
SELECT sno 学生姓名,kc1,kc2,
SUM(kc1+kc2) 总成绩
FROM score
GROUP BY sno,kc1,kc2

SELECT sno 学生姓名,kc1,kc2,
SUM(kc1+kc2) OVER(PARTITION BY sno) 总成绩
FROM score

#这种情况下的窗口函数,和分组group by差不多,只不过一个是查询的时候分组,一个是from 表之后分组

SELECT sno 学生姓名,SUM(score) 总成绩
FROM sc
GROUP BY sno

SELECT DISTINCT sno 学生姓名,
SUM(score) OVER(PARTITION BY sno) 总成绩
FROM sc

命名窗口 window wind_name as ()

当一个窗口被多次引用的时候,在每个over后面都写一遍定义就显得有些繁琐了,此场景可以通过命名窗口优化:一次定义,多次引用。

命名窗口的定义是通过 window wind_name as () 来进行定义的,括号内的部分就是原over子句后的窗口定义,在用over关键字调用窗口时,直接引用窗口名wind_name即可:

select x1,
sum(x2) over w    -- 通过名称 w 引用窗口  (为了好看,也可以起个别名)
from 表名
window w as (partition by x1);  -- 命名窗口定义

重复出现的分类就单独拎出来,做一个窗口函数去定义,在上面进行调用

SELECT sno,
SUM(score) OVER(PARTITION BY sno) AS score
FROM sc

将 PARTITION BY sno 单独拎出来命名为 w ,在上面over 后面进行调用
SELECT sno,
SUM(score) OVER w AS score
FROM sc
WINDOW w AS (PARTITION BY sno)

专用窗口函数 row_number()、rank()、dense_rank()

专用窗口函数在使用时必须搭配 over 关键字

建表
CREATE TABLE score(
sno VARCHAR(10) NOT NULL ,
kc1 VARCHAR(10) NOT NULL,
kc2 VARCHAR(10) NOT NULL
);
添数据
INSERT INTO score
(sno, kc1, kc2) VALUES
("张三", 34, 58),
("李四", 45, 87),
("王五", 76, 34);

插入数据
 INSERT INTO score
 (sno,kc1) VALUES
 ('赵六',76),('钱七',58),('孙八',35),('姬九',34);
 报错:kc2 设置非空,却没有插入数据
 解决办法:修改kc2属性,取消非空
  ALTER TABLE score 
 CHANGE COLUMN kc2 kc2 VARCHAR(10);

row_number() over window

ROW_NUMBER()函数,对同一个字段排序,排名是连续的,即使出现相同,也不会出现并列排名
rank()

RANK()函数,对同一个字段排序,出现相同时,会并列排名,并且会出现排名间隙
dense_rank()

DENSE_RANK()函数,对同一个字段排序,出现相同时,会出现并列排名

只按照一个关键词排序

 #根据kc1进行降序,不需要分区,所以不需要partition by
SELECT sno,kc1,
RANK() OVER(ORDER BY kc1) ran,
DENSE_RANK() OVER(ORDER BY kc1) den,
ROW_NUMBER() OVER(ORDER BY kc1) ro
FROM score

调用命令窗口:
SELECT sno,kc1,
RANK() OVER w ran,
DENSE_RANK() OVER w den,
ROW_NUMBER() OVER w ro
FROM score
WINDOW w AS (ORDER BY kc1)


成绩中存在各科,多种类排序

#整体排序
SELECT sc.*,
RANK() OVER(ORDER BY score) ran
FROM sc
#各科排序
SELECT sc.* ,RANK() OVER(PARTITION BY cno ORDER BY score DESC) 'rank' FROM sc;
SELECT sno,cno,score ,RANK() OVER(PARTITION BY cno ORDER BY score DESC) 'rank' FROM sc;

SELECT sno,cno,score ,
RANK() OVER w 'rank',
DENSE_RANK() OVER w 'DENSE_RANK',
ROW_NUMBER() OVER w 'ROW_NUMBER'
FROM sc
WINDOW w AS (PARTITION BY cno ORDER BY score DESC)

排序 order by

-- 先优先 math 升序;若 math 相等,则按 Chinese 降序;若都相等,按 id 升序
select * from student order by math asc, chinese desc, id;
-- 使用表达式 + 别名排序
select  name, math + chinese + english 总分 from student order by 总分;

分页 limit

-- 从下标0开始,筛选5条结果
select * from student limit 5;
-- 从下标2开始,筛选5条结果
select * from student limit 2, 5;
-- 筛选5条结果,从下标2开始。这种写法意思更明确
select * from student limit 5 offset 2;

-- 综合运用
-- 查询数学成绩高于80分,且排名前三的学生
select name, math from student where math > 80 order by math desc limit 3;

聚合函数

count(*):统计所有的行数
count(列名):统计某列的值总和
sum(列名):求一列的和
avg(列名):求一列的平均值
max(列名):求一列的最大值
min(列名):求一列的最小值

聚合函数和group by 的使用

SELECT sum(*) FROM 表名 WHERE 条件 GROUP BY 列名;

-- 查询每种角色的最高工资、最低工资、平均工资
select role, max(salary), min(salary), avg(salary) from emp group by role;

-- 统计每种角色薪资高于500的人数
select role, count(*) from emp where salary > 500 group by role;

-- 多聚合,在不同列的组合下进行聚合查询
select company, role, count(*) from emp2 group by company, role;

聚合函数和group by、having使用

-- having关键字用于聚合之后进行过滤操作
select role, avg(salary) from emp group by role having avg(salary) > 300;

注意顺序:where > group by > having


多表查询

#方式1:
SELECT ...,....,...
FROM ...,...,....
WHERE 多表的连接条件 AND 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
#方式2:
SELECT ...,....,...
FROM ... JOIN ...
ON 多表的连接条件
JOIN ...
ON ...
WHERE 不包含组函数的过滤条件
AND/OR 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
#其中:
#(1)from:从哪些表中筛选
#(2)on:关联多表查询时,去除笛卡尔积
#(3)where:从表中筛选的条件
#(4)group by:分组依据
#(5)having:在统计结果中再次筛选
#(6)order by:排序
#(7)limit:分页

多表连接的分类

可以根据3个角度进行分类:

角度1:是否使用"="符号

等值接连 :where条件中,表字段与表字段直接使用等于符号("=")进行判断
非等值连接:where条件中,表字段与表字段使用非"="符号,如:<=(小于等于)、>=(大于等于)、between and等等。

角度2:连接表的数量是否大于1

自连接 :一张表直接的关联查询,自己表连接自己进行查询,如菜单表查子级
非自连接:多表关联查询

角度3:多表关联时,是否只查询有关联的数据

内连接 :合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行
外连接:合并具有同一列的两个以上的表的行,结果集中包含一个表与另一个表匹配的行之外,还包含了左表 或 右表不匹配的行


内连接

只显示两者交叉的对方,其他的完全不包含

select 字段 from 表1 (inner)  join 表2 on 连接条件 where 其他条件; 
select 字段 from 表1,表2 where 表1.xx=表2.xx;

-- inner 可以省略
select * from users join articles on uid = author_id where users.name = '小红';

-- 查询作者对应的书籍
select name, title from users inner join articles on users.uid = articles.author_id;	

左连接

左外连接(left outer join,可缩写为left join):两个表连接过程中,除了返回满足条件的行以外,还会返回左表中不满足条件的行,这种连接称为左连接

select 字段名 from 表名1 left join 表名2 on 连接条件;

select
    t1.id       -- 学生ID
     ,t1.name    -- 学生姓名
     ,t1.age     -- 学生年龄
     ,t2.name    -- 班级名称
from student t1
left join classinfo t2    --注意:left join是缩写,也可以写为:left outer join
on t1.classid=t2.classid

右连接

右外连接(right outer join,可缩写为right join):两个表连接过程中,除了返回满足条件的行以外,还会返回右表中不满足条件的行,这种连接称为右连接

select 字段名 from 表名1 right join 表名2 on 连接条件;

select
    t2.id       -- 学生ID
    ,t2.name    -- 学生姓名
    ,t2.age     -- 学生年龄
    ,t1.name    -- 班级名称
from classinfo t1
right join student t2
on t1.classid=t2.classid

全连接

全连接(full outer join,可缩写为full join):又称为"满外连接",两个表连接过程中,返回两表直接的所有数据,这种连接称为全连接

MySQL不支持全连接,但是Oracle支持

SQL99全连接写法(Oracle):
关键字:full join ... on ... 或者 full outer join ... on ...

MySQL实现全连接,需要使用关键字"union"或者"union all"

union:联合、合并的意思

union:对两个查询的结果集,进行合并操作,会对重复的数据进行去重,同时进行默认规则(主键升序)的排序(因此效率比较低)。
union all:对两个查询的结果集,进行合并操作,不对数据进行去重,也不进行排序,直接把两个结果进行合并(效率高)。

union 进行去重

union all 不去重

注: union和union all使用时,select下的字段数量必须一致,否则会报错


自连接

自连接是指将自身的某一列看成一个表,在同一张表连接自身另一列进行查询

#查询c001比c002成绩高的同学信息
SELECT s1.sno 学生姓名,s1.score c001成绩,s2.score c002成绩
FROM (SELECT sno,score FROM sc WHERE cno='c001') s1 
JOIN (SELECT sno,score FROM sc WHERE cno='c002') s2
ON s1.`sno`=s2.`sno`
WHERE s1.score>s2.score


感觉也是把两张表连起来(普通多表查询与内连接区别)

      -- 区别  :  on是先筛选后关联,优先级高,所以先做hash筛选匹配,再两张表合并
             --  where 是先关联合并表后   筛选匹配(量大),
           --  on指匹配到一条需要的记录后就结束,其他的不匹配,然后合并表,
           -- 而where的会一直匹配直到结束,再合并表
           
         --  on 匹配到相同的数据 ->   join (合并)  ->  select查询 
        --  合并biao1,biao2 ,    -->where 对合并的所以信息筛选 -->select 查询
         -- on 效率高    先hash,后合并,效率  0 logN
         -- where 效率低:  多个from笛卡尔集 合并 再筛选  0(n^2)

笛卡尔积

数学上,有两个集合A={a,b},B={1,2,3},则两个集合的笛卡尔积={{a,1}, {a,2}, {a,3}, {b,1}, {b,2}, {b,3}} 列出所有情况,一共是2*3=6条记录

在数据库中,笛卡尔积是多表查询没有连接条件时返回的表结果

mysql> select *from 表1,表2;

实际开发中应该避免全笛卡尔积 ----在 where 加入有效的连接条件【等值连接】

1.指定连接条件 (等于、大于、小于)

2.指定查询条件 (少用select *)


行转列

行转列,值将一行内的数据'炸裂'成各个行(case 查询词句 when '列名' then 值 else 返回值 end)

将需要拆分的那一列,通过group by函数查找出总类别,放置到第一列;
通过 case ... when ... then ... else ... end 函数查找出对应的(科目)列名

原数据

#行转列
SELECT sno,
MAX(CASE cno WHEN 'c001' THEN score ELSE 0 END) AS 'c001',
MAX(CASE cno WHEN 'c002' THEN score ELSE 0 END) AS 'c002',
MAX(CASE cno WHEN 'c003' THEN score ELSE 0 END) AS 'c003'
FROM sc
GROUP BY sno
SELECT cno,
MAX(CASE sno WHEN 's001' THEN score ELSE 0 END) AS 's001',
MAX(CASE sno WHEN 's002' THEN score ELSE 0 END) AS 's002',
MAX(CASE sno WHEN 's003' THEN score ELSE 0 END) AS 's003'
FROM sc
GROUP BY cno

查询的时候用case ... when ... then ... else ... end 选择需要进行转行的字段以及字段结果,

即当Subject是xx的时候,选择Subject对应的Score作为Subject的成绩,

这里需要注意case when then的结果要用max函数包裹,不然结果也会变成行,但是每行只有一科的成绩,用max包裹就是选择最大成绩,把多行合并成一行完成行转列。

问题???? 如果只知道课程编号的情况下,如何把行炸裂成 课程名称?

这种情况下,一定是要'起别名'的,但是,如果表中本没有课程名称,只有课程编号,要怎么去炸裂成课程名称?

难道只能查询两次,看着第一次的查询结果重新 起别名 吗????

SELECT sno,
MAX(CASE cno WHEN 'c001' THEN score ELSE 0 END) AS 'j2se',
MAX(CASE cno WHEN 'c002' THEN score ELSE 0 END) AS 'java web',
MAX(CASE cno WHEN 'c003' THEN score ELSE 0 END) AS 'ssh'
FROM sc 
GROUP BY sno

列转行

将想要的列名,通过select 查询出来,通过union全连接拼接到下方

目前是学生-课程1成绩-课程2成绩 想变成 学生-课程-成绩

建表
CREATE TABLE score(
sno VARCHAR(10) NOT NULL ,
kc1 VARCHAR(10) NOT NULL,
kc2 VARCHAR(10) NOT NULL
);
添数据
INSERT INTO score
(sno, kc1, kc2) VALUES
("张三", 34, 58),
("李四", 45, 87),
("王五", 76, 34);

目前的表内容

SELECT sno,kc1 course,kc1 score
FROM score 

出现错误,只修改了'列名',里面的数据还是传进来了,但并不需要他传参
解决办法: 加引号,加引号之后,只会传当前字符段,不在传参

SELECT sno,'kc1' course,kc1 score
FROM score 

将两个科目的内容拼一下

SELECT sno,'kc1' course,kc1 score
FROM score 
UNION
SELECT sno,'kc2' course ,kc2 score
FROM score
ORDER BY sno,course
相关推荐
奶糖趣多多12 分钟前
Redis知识点
数据库·redis·缓存
CoderIsArt1 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
师太,答应老衲吧3 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
Channing Lewis4 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
追风林5 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker
毕业设计制作和分享6 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil276 小时前
Redis - String 字符串
数据库·redis·缓存
Hsu_kk7 小时前
MySQL 批量删除海量数据的几种方法
数据库·mysql
编程学无止境7 小时前
第02章 MySQL环境搭建
数据库·mysql