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
相关推荐
云和数据.ChenGuang14 分钟前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
woshilys42 分钟前
sql server 查询对象的修改时间
运维·数据库·sqlserver
Hacker_LaoYi42 分钟前
SQL注入的那些面试题总结
数据库·sql
建投数据2 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
Hacker_LaoYi3 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀3 小时前
Redis梳理
数据库·redis·缓存
独行soc3 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
你的微笑,乱了夏天3 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺3 小时前
分布式系统架构:服务容错
数据库·架构
独行soc4 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘