MysQL使用一高级应用(下)

Wesley13
• 阅读 391

连接查询

  • 连接查询分类如下:
    • 表A inner join 表B:表A与表B匹配的行会出现在结果中
    • 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充
    • 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充
  • 在查询或条件中推荐使用“表名.列名”的语法
  • 如果多个表中列名不重复可以省略“表名.”部分
  • 如果表的名称太长,可以在表名后面使用' as 简写名'或' 简写名',为表起个临时的简写名称

练习

  • 查询学生的姓名、平均分

    select students.sname,avg(scores.score) from scores inner join students on scores.stuid=students.id group by students.sname;

  • 查询男生的姓名、总分

    select students.sname,avg(scores.score) from scores inner join students on scores.stuid=students.id where students.gender=1 group by students.sname;

  • 查询科目的名称、平均分

    select subjects.stitle,avg(scores.score) from scores inner join subjects on scores.subid=subjects.id group by subjects.stitle;

  • 查询未删除科目的名称、最高分、平均分

    select subjects.stitle,avg(scores.score),max(scores.score) from scores inner join subjects on scores.subid=subjects.id where subjects.isdelete=0 group by subjects.stitle;

自关联

  • 设计省信息的表结构provinces

    • id
    • ptitle
  • 设计市信息的表结构citys

    • id
    • ctitle
    • proid
  • citys表的proid表示城市所属的省,对应着provinces表的id值

  • 问题:能不能将两个表合成一张表呢?

  • 思考:观察两张表发现,citys表比provinces表多一个列proid,其它列的类型都是一样的

  • 意义:存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还要存储区、乡镇信息,都增加新表的开销太大

  • 答案:定义表areas,结构如下

    • id
    • atitle
    • pid
  • 因为省没有所属的省份,所以可以填写为null

  • 城市所属的省份pid,填写省所对应的编号id

  • 这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的,城市信息的pid引用的是省信息的id

  • 在这个表中,结构不变,可以添加区县、乡镇街道、村社区等信息

  • 创建areas表的语句如下:

    create table areas( id int primary key, atitle varchar(20), pid int, foreign key(pid) references areas(id) );

  • 从sql文件中导入数据

    source areas.sql;

  • 查询一共有多少个省

  • 查询省的名称为“山西省”的所有城市

    select city.* from areas as city inner join areas as province on city.pid=province.id where province.atitle='山西省';

  • 查询市的名称为“广州市”的所有区县

    select dis.,dis2. from areas as dis inner join areas as city on city.id=dis.pid left join areas as dis2 on dis.id=dis2.pid where city.atitle='广州市';

子查询

  • 查询支持嵌套使用

  • 查询各学生的语文、数学、英语的成绩

    select sname, (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='语文' and stuid=stu.id) as 语文, (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='数学' and stuid=stu.id) as 数学, (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='英语' and stuid=stu.id) as 英语 from students stu;

字符串函数

  • 查看字符的ascii码值ascii(str),str是空串时返回0

    select ascii('a');

  • 查看ascii码值对应的字符char(数字)

    select char(97);

  • 拼接字符串concat(str1,str2...)

    select concat(12,34,'ab');

  • 包含字符个数length(str)

    select length('abc');

  • 截取字符串

    • left(str,len)返回字符串str的左端len个字符
    • right(str,len)返回字符串str的右端len个字符
    • substring(str,pos,len)返回字符串str的位置pos起len个字符

    select substring('abc123',2,3);

  • 去除空格

    • ltrim(str)返回删除了左空格的字符串str
    • rtrim(str)返回删除了右空格的字符串str
    • trim([方向 remstr from str)返回从某侧删除remstr后的字符串str,方向词包括both、leading、trailing,表示两侧、左、右

    select trim(' bar '); select trim(leading 'x' FROM 'xxxbarxxx'); select trim(both 'x' FROM 'xxxbarxxx'); select trim(trailing 'x' FROM 'xxxbarxxx');

  • 返回由n个空格字符组成的一个字符串space(n)

    select space(10);

  • 替换字符串replace(str,from_str,to_str)

    select replace('abc123','123','def');

  • 大小写转换,函数如下

    • lower(str)
    • upper(str)

    select lower('aBcD');

数学函数

  • 求绝对值abs(n)

    select abs(-32);

  • 求m除以n的余数mod(m,n),同运算符%

    select mod(10,3); select 10%3;

  • 地板floor(n),表示不大于n的最大整数

    select floor(2.3);

  • 天花板ceiling(n),表示不小于n的最大整数

    select ceiling(2.3);

  • 求四舍五入值round(n,d),n表示原数,d表示小数位置,默认为0

    select round(1.6);

  • 求x的y次幂pow(x,y)

    select pow(2,3);

  • 获取圆周率PI()

    select PI();

  • 随机数rand(),值为0-1.0的浮点数

    select rand();

  • 还有其它很多三角函数,使用时可以查询文档

日期时间函数

  • 获取子值,语法如下

    • year(date)返回date的年份(范围在1000到9999)
    • month(date)返回date中的月份数值
    • day(date)返回date中的日期数值
    • hour(time)返回time的小时数(范围是0到23)
    • minute(time)返回time的分钟数(范围是0到59)
    • second(time)返回time的秒数(范围是0到59)

    select year('2016-12-21');

  • 日期计算,使用+-运算符,数字后面的关键字为year、month、day、hour、minute、second

    select '2016-12-21'+interval 1 day;

  • 日期格式化date_format(date,format),format参数可用的值如下

    • 获取年%Y,返回4位的整数

      * 获取年%y,返回2位的整数

      * 获取月%m,值为1-12的整数

    • 获取日%d,返回整数

      * 获取时%H,值为0-23的整数

      * 获取时%h,值为1-12的整数

      * 获取分%i,值为0-59的整数

      * 获取秒%s,值为0-59的整数

    select date_format('2016-12-21','%Y %m %d');

  • 当前日期current_date()

    select current_date();

  • 当前时间current_time()

    select current_time();

  • 当前日期时间now()

    select now();

视图

  • 对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情

  • 解决:定义视图

  • 视图本质就是对查询的一个封装

  • 定义视图

    create view stuscore as select students.*,scores.score from scores inner join students on scores.stuid=students.id;

  • 视图的用途就是查询

    select * from stuscore;

事务

  • 当一个业务逻辑需要多个sql完成时,如果其中某条sql语句出错,则希望整个操作都退回

  • 使用事务可以完成退回的功能,保证业务逻辑的正确性

  • 事务四大特性(简称ACID)

    • 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行
    • 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
    • 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的
    • 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障
  • 要求:表的类型必须是innodb或bdb类型,才可以对此表使用事务

  • 查看表的创建语句

    show create table students;

  • 修改表的类型

    alter table '表名' engine=innodb;

  • 事务语句

    开启begin; 提交commit; 回滚rollback;

示例1

  • 步骤1:打开两个终端,连接mysql,使用同一个数据库,操作同一张表

    终端1:

    select * from students;

    终端2: begin; insert into students(sname) values('张飞');

  • 步骤2

    终端1: select * from students;

  • 步骤3

    终端2:

    commit;

    终端1: select * from students;

示例2

  • 步骤1:打开两个终端,连接mysql,使用同一个数据库,操作同一张表

    终端1:

    select * from students;

    终端2: begin; insert into students(sname) values('张飞');

  • 步骤2

    终端1: select * from students;

  • 步骤3

    终端2:

    rollback;

    终端1: select * from students;

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
oracle查询表数据并重新插入到本表
oracle查询表数据并重新插入到本表CreateTime2018年5月17日10:30:10Author:Marydon1.情景描述查询表中数据SELECTFROMat_aut
Wesley13 Wesley13
2年前
Oracle一张表中实现对一个字段不同值和总值的统计(多个count)
需求:统计WAIT\_ORDER表中的工单总数、未处理工单总数、已完成工单总数、未完成工单总数。表结构:为了举例子方便,WAIT\_ORDER表只有两个字段,分别是ID、STATUS,其中STATUS为工单的状态。1表示未处理,2表示已完成,3表示未完成总数。 SQL:  1.SELECT   2
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这