python数据库-MySQL数据库高级查询操做(51)

1、什么是关系?

一、分析:有这么一组数据关于学生的数据

学号、姓名、年龄、住址、成绩、学科、学科(语文、数学、英语)

咱们应该怎么去设计储存这些数据呢?python

二、先考虑第一范式:列不可在拆分原则

  这里面学科包含了三个学科,因此学科拆分为:语文学科、数学学科、英语学科,一样的成绩也要拆分为语文成绩、数学成绩、英语成绩。这样既知足了第一范式,各列能够设计为:mysql

学号、姓名、年龄、住址、语文学科、数学学科、英语学科、语文成绩、数学成绩、英语成绩

三、在考虑第二范式:惟一标识

  也就是说在1NF的基础上,非Key属性必须彻底依赖于主键,第二范式(2NF)要求数据库表中的每一个实例或记录必须能够被惟一地区分。选取一个能区分每一个实体的属性或属性组,做为实体的惟一标识。即肯定主键,咱们能够选取学号为主键sql

四、接着在考虑第三范式:

  确保表中各列与主键列直接相关,而不是间接相关。即各列与主键列都是一种直接依赖关系,则知足第三范式。 

  不难发如今这么多列中,年龄、住址和成绩、学科没有直接关系,也就是说我考多少分,和年龄及住址都无关,他们都是学生的信息,但都是不相关的信息,因此根据第三范式,咱们须要将这些数据根据其相关性拆分为多个表。数据库

五、表与表之间的关系

  若是咱们要想找到张三的语文成绩,那么咱们就必须去成绩表中查找,由于成绩表中保存的全部人的全部学科成绩。可是在成绩表中查找的时候,须要从省标中查到张三的学号(stu_id)和从学科表中查到语文学科(sub_id)的编号,这个时候这三张表就发生了关系,这也就是关系型数据库的精髓,而根据这种表与表之间的关系也会衍生出不少的查询的高级操做函数

 

2、外键(foreign key)

外键约束:用于限制主表与从表数据完整性。ui

alter table scores  add constraint 'stu_score_fk' foreign key(stu_id) references students(stu_id);
  • 将scores表的stu_id外键关联到students表的stu_id字段(说明:这里scores表里面字段stu_id和students表里的stu_id重名了,最好避免重名)
  • 每一个外键都有一个名字,能够经过constraint指定
  • 存在外键的表,称之为从表(子表),外键指向的表,称之为主表(父表)。
  • 做用:保持数据一致性,完整性,主要目的是控制存储在外键表(从表)中的数据。例如,此时在从表插入或者修改数据时,若是stu_id的值在students表中不存在则会报错
  • 外键也能够在建立表时能够直接建立约束

语法:spa

 foreign key (外键字段) references 主表名 (关联字段)
例如:
create table scores(
id int primary key auto_increment,
stu_id int,
sub_id int,
score decimal(5,2),
foreign key(stuid) references students(id),
foreign key(subid) references subjects(id)
);

[主表记录删除时的动做] [主表记录更新时的动做],此时须要检测一个从表的外键须要约束为主表的已存在的值。外键在没有关联的状况下,能够设置为null.前提是该外键列,没有not null。

设计

3、外键的级联操做

  • 在删除或者修改students表的数据时,若是这个stu_id值在scores中已经存在,则会抛异常
  • 推荐使用逻辑删除,还能够解决这个问题
  • 能够建立表时指定级联操做,也能够在建立表后再修改外键的级联操做
alter table scores add constraint stu_sco foreign key(stu_id) references students(stu_id) on delete cascade;

除了on delete还有on update都要注意级联操做版本控制

级联操做的类型包括:rest

  • restrict(限制):默认值,抛异常,拒绝父表删除或者更新
  • cascade(级联):若是主表的记录删掉,则从表中相关联的记录都将被删除,若是主表修改记录,则从表记录也将被修改
  • set null:将外键设置为空
  • no action:什么都不作

 

4、连接查询

在讲解第一个问题关系的时候,咱们提到了,若是要查找张三的语文成绩,须要用到三个表,当咱们查询结果来源于多张表的时候就须要使用链接查询

连接查询关键:找到表间的关系,当前的关系是

  • students表的stu_id---scores表的stu_id
  • subjects表的sub_id---scores表的sub_id

select students.stu_name,subjects.sub_name,scores.score 
from scores
inner join students on scores.stu_id=students.stu_id 
inner join subjects on scores.sub_id=subjects.sub_id 
where students.stu_name='张三' and subjects.sub_name='语文';
+----------+----------+-------+
| stu_name | sub_name | score |
+----------+----------+-------+
| 张三      | 语文     |    80 |
+----------+----------+-------+
  • 结论:当须要对有关系的多张表进行查询时,须要使用链接join
  • 链接查询分类以下:
    • 表A inner join 表B:表A与表B匹配的行会出如今结果中
    • 表A left join 表B:表A与表B匹配的行会出如今结果中,外加表A中独有的数据,未对应的数据使用null填充
    • 表A right join 表B:表A与表B匹配的行会出如今结果中,外加表B中独有的数据,未对应的数据使用null填充
    • 在查询或条件中推荐使用“表名.列名”的语法
    • 若是多个表中列名不重复能够省略“表名.”部分
    • 若是表的名称太长,能够在表名后面使用' as 简写名'或' 简写名',为表起个临时的简写名称

 

5、视图

  视图就像咱们python里面的函数同样,对SQL语言代码块的封装

    • 对于复杂的查询,在屡次使用后,维护是一件很是麻烦的事情
    • 解决:定义视图
    • 视图本质就是对查询的一个封装
    • 定义视图
create view stuscore as select students.stu_name,subjects.sub_name,scores.score from scores inner join students on scores.stu_id=students.stu_id inner join subjects on scores.sub_id=subjects.sub_id;

这句话的意思就是用stuscore就至关于后面红色很长的一段SQL语句:

mysql> select *from stuscore;
+----------+----------+-------+
| stu_name | sub_name | score |
+----------+----------+-------+
| 张三     | 语文     |    80 |
| 张三     | 数学     |    85 |
| 张三     | 英语     |    88 |
| 李四     | 语文     |    83 |
| 李四     | 数学     |    84 |
| 李四     | 英语     |    87 |
| 王五     | 语文     |    81 |
| 王五     | 数学     |    85 |
| 王五     | 英语     |    85 |
| 赵六     | 语文     |    88 |
| 赵六     | 数学     |    88 |
| 赵六     | 英语     |    87 |
| 侯七     | 语文     |    84 |
| 侯七     | 数学     |    83 |
| 侯七     | 英语     |    82 |
+----------+----------+-------+

 

 6、自链接查询

  有时在信息查询时须要进行对自身链接(自链接)自链接是单边操做,因此咱们须要为表定义别名。举例说明,下面是一个新的学生成绩表,在下表中咱们要找到比张三成绩高的。

+--------+----------+-----------+
| stu_id | stu_name | stu_score |
+--------+----------+-----------+
|      1 | 张三     |        90 |
|      2 | 李四     |        85 |
|      3 | 王五     |        80 |
|      4 | 赵六     |        95 |
|      5 | 侯七     |       100 |
+--------+----------+-----------+

  通常状况咱们看到这张表咱们第一时间用语句进行操做:

select * from Score where stu_score>90;

  可想而知,这是有多么简单,假设你并不知道数据库中张三的成绩是90或者数据量至关庞大呢?做为一个数据库管理员,咱们就要用别的方式迅速找出所须要的数据。

 

方式一:分步查找:最简单的一种方式,也是最容易想到的操做“

select stu_score from Score where stu_name='张三';//得出张三的成绩
select *from Score where stu_score>90;

  与采用自链接的方式相比,这种方法须要对中间结果进行人工干预,显然不利于程序中的自动处理操做。

方式二:自链接方式:

select * from Score as a,Score as b where a.stu_name='张三' and a.stu_score<b.stu_score;
+--------+----------+-----------+--------+----------+-----------+
| stu_id | stu_name | stu_score | stu_id | stu_name | stu_score |
+--------+----------+-----------+--------+----------+-----------+
|      1 | 张三      |        90 |      4 | 赵六     |        95 |
|      1 | 张三      |        90 |      5 | 侯七     |       100 |
+--------+----------+-----------+--------+----------+-----------+

若是不想把张三的信息打印出来咱们能够调整SQL语句为:

select b.* from Stu_score as a,Stu_score as b where a.stu_name='张三' and a.stu_score<b.stu_score;
+--------+----------+-----------+
| stu_id | stu_name | stu_score |
+--------+----------+-----------+
|      4 | 赵六      |        95 |
|      5 | 侯七      |       100 |
+--------+----------+-----------+

注意:别名 a,b虽然名称不一样,可是同一个表,定义别名的目的是更方便在自身进行删选。
执行select经过(中间表)所获得的b.*,,就是最终结果。

 

7、子查询

子查询也是经常使用的一种方式,就是在select里嵌套select。仍是上面的例子,咱们用子查询实现以下:

select * from Stu_score where stu_score>(select stu_score from Stu_score where stu_name='张三'); 
+--------+----------+-----------+
| stu_id | stu_name | stu_score |
+--------+----------+-----------+
|      4 | 赵六      |        95 |
|      5 | 侯七      |       100 |
+--------+----------+-----------+

 

8、内置函数

一、字符串函数

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

mysql> select ascii('a'); +------------+
| ascii('a') |
+------------+
|         97 |
+------------+

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

mysql> select char(97); +----------+
| char(97) |
+----------+
| a        |
+----------+

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

select concat(12,34,'ab'); +--------------------+
| concat(12,34,'ab') |
+--------------------+
| 1234ab             |
+--------------------+

四、包含字符个数length(str)

mysql> select length('abc'); +---------------+
| length('abc') |
+---------------+
|             3 |
+---------------+

五、截取字符串

  • left(str,len)返回字符串str的左端len个字符
  • right(str,len)返回字符串str的右端len个字符
  • substring(str,pos,len)返回字符串str的位置pos起len个字符
mysql> select substring('abc123',2,3); +-------------------------+
| substring('abc123',2,3) |
+-------------------------+
| bc1                     |
+-------------------------+

六、去除空格

  • ltrim(str)返回删除了左空格的字符串str
  • rtrim(str)返回删除了右空格的字符串str
  • trim([方向 remstr from str)返回从某侧删除remstr后的字符串str,方向词包括both、leading、trailing,表示两侧、左、右
mysql> select trim(' bar '); +------------------+
| trim('  bar   ') |
+------------------+
| bar              |
+------------------+
mysql> select trim(leading 'x' FROM 'xxxbarxxx'); +------------------------------------+
| trim(leading 'x' FROM 'xxxbarxxx') |
+------------------------------------+
| barxxx                             |
+------------------------------------+
mysql> select trim(trailing 'x' FROM 'xxxbarxxx'); +-------------------------------------+
| trim(trailing 'x' FROM 'xxxbarxxx') |
+-------------------------------------+
| xxxbar                              |
+-------------------------------------+
mysql> select trim(both 'x' FROM 'xxxbarxxx'); +---------------------------------+
| trim(both 'x' FROM 'xxxbarxxx') |
+---------------------------------+
| bar                             |
+---------------------------------+

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

mysql> select replace('abc123','123','def');
+-------------------------------+
| replace('abc123','123','def') |
+-------------------------------+
| abcdef                        |
+-------------------------------+

八、大小写转换,函数以下

  • lower(str)
  • upper(str)
mysql> select lower('aBcD');
+---------------+
| lower('aBcD') |
+---------------+
| abcd          |
+---------------+

二、数学函数

一、求绝对值abs(n)

mysql> select abs(-32);
+----------+
| abs(-32) |
+----------+
|       32 |
+----------+

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

mysql> select mod(10,3);
+-----------+
| mod(10,3) |
+-----------+
|         1 |
+-----------+

mysql> select 10%3;
+------+
| 10%3 |
+------+
|    1 |
+------+

三、floor(n),表示不大于n的最大整数

mysql> select floor(2.3);
+------------+
| floor(2.3) |
+------------+
|          2 |
+------------+

四、ceiling(n),表示不小于n的最大整数

mysql> select ceiling(2.3);
+--------------+
| ceiling(2.3) |
+--------------+
|            3 |
+--------------+

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

mysql> select round(1.6);
+------------+
| round(1.6) |
+------------+
|          2 |
+------------+

六、求x的y次幂pow(x,y)

mysql> select pow(2,3);
+----------+
| pow(2,3) |
+----------+
|        8 |
+----------+

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

mysql> select rand();
+--------------------+
| rand()             |
+--------------------+
| 0.0713081630610937 |
+--------------------+

三、日期时间函数

  • 获取子值,语法以下
    • 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)
mysql> select year('2019-7-11');
+-------------------+
| year('2019-7-11') |
+-------------------+
|              2019 |
+-------------------+
  • 日期计算,使用+-运算符,数字后面的关键字为year、month、day、hour、minute、second
mysql> select '2019-7-11'+interval 1 day;
+----------------------------+
| '2019-7-11'+interval 1 day |
+----------------------------+
| 2019-07-12                 |
+----------------------------+

日期格式化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的整数

 

9、事物

  • 当一个业务逻辑须要多个sql语句完成时,若是其中某条sql语句出错,则但愿整个操做都退回
  • 使用事务能够完成退回的功能,保证业务逻辑的正确性
  • 事务四大特性(简称ACID)
    • 原子性(Atomicity):事务中的所有操做在数据库中是不可分割的,要么所有完成,要么均不执行
    • 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
    • 隔离性(Isolation):事务的执行不受其余事务的干扰,事务执行的中间结果对其余事务必须是透明的
    • 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即便数据库出现故障
  • 要求:表的类型必须是innodb或bdb类型,才能够对此表使用事务
  • 查看表的建立语句
show create table Stu_score;
  • 修改表的类型:alter table '表名' engine=innodb;
alter table Stu_score engine=innodb;
  • 事务语句
开启begin;
提交commit;
回滚rollback;

  在begin;后面写咱们要操做的SQL语句组合也就是咱们所谓的要执行的事物,可是这个时候写好的SQL语句就算咱们回车以后,也不会执行,知道commit;执行以后才会被执行到数据库中,rollback回滚是咱们begin;以后发现咱们写错了,或者不想执行了,均可以在commit;以前回滚到上一次commit;的状态,很像版本控制器SVN和GIT同样

相关文章
相关标签/搜索