python必坑知识点04
1.关系型和非关系型数据库区别
关系型:支持常用的sql语句,本质相当于一个二维表模型,表之间可以有关联、外键等
非关系型:可以有多种的状态的命令,k、v键值对等,支持高并发,效率高,可用于集群的分布式均衡负载
2.MySQL数据库事务特性有哪些?
四大特性:
原子性:不可分割,要么都成功,要么都失败回滚
一致性:事务执行前后数据完整性一致
隔离性:事务执行中,不受到外界的干扰
持久性:事务执行结束,数据持久到数据库中
3.通俗地讲一下三个范式
范式一:记录的原子性,不可拆分
范式二:唯一性
范式三:冗余性
为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。
在实际开发中最为常见的设计范式有三个:
1.第一范式(确保每列保持原子性)
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到“地址”这个属性,本来直接将“地址”属性设计成一个数据库表的字段就行。但是如果系统经常会访问“地址”属性中的“城市”部分,那么就非要将“地址”这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算满足了数据库的第一范式,如下表所示。
上表所示的用户信息遵循了第一范式的要求,这样在对用户使用城市进行分类的时候就非常方便,也提高了数据库的性能。
2.第二范式(确保表中的每列都和主键相关)
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键,如下表所示。
订单信息表
这样就产生一个问题:这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。
而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。如下所示。
这样设计,在很大程度上减小了数据库的冗余。如果要获取订单的商品信息,使用商品编号到商品信息表中查询即可。
3.第三范式(确保每列都和主键列直接相关,而不是间接相关)
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。
这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余。
4.主键、外键和索引的区别
(1)概念
主键:唯一标识一条记录,不能有重复,不允许为空。
外键:表的外键是另一表的主键,外键可以有重复,可以是空值。
索引:该字段没有重复值,但可以有一个空值。
(2)作用
主键:用来保证数据完整性
外键:用于和其他表建立联系用的
索引:提高查询排序的速度
(3)个数
主键:主键只能有一个
外键:一个表可以有多个外键
索引:一个表可以有多个唯一索引
5.commit和rollback的理解
commit:sql执行成功,数据提交到数据库中
rollback:sql执行失败,不会提交到数据库,数据回滚到执行sql之前
6.SQL语句查询优化有哪些方法
建立索引并命中索引,在查询的时候,要尽量让数据库引擎使用索引。加入explain执行计划
1.尽量避免使用select *
2.尽量避免使用!=
3.尽量避免使用or
优化方式:可以用union代替or。如下:
SELECT * FROM t WHERE username="hkw"
UNION
SELECT * FROM t WHERE nickname="jon"
4.尽量避免使用in和not in
优化方式:如果是连续数值,可以用between代替
如果是子查询,可以用exists代替。如下:
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)
5.尽量避免在字段开头模糊查询
SELECT * FROM t WHERE username LIKE '%li%'
优化方式:尽量在字段后面使用模糊查询。如下:
SELECT * FROM t WHERE username LIKE 'li%'
6.尽量避免进行null值的判断
SELECT * FROM t WHERE score IS NULL
优化方式:可以给字段添加默认值0,对0值进行判断。如下:
SELECT * FROM t WHERE score = 0
7.尽量避免在where条件中等号的左侧进行表达式、函数操作
SELECT * FROM t2 WHERE score/10 = 9
SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'
优化方式:可以将表达式、函数操作移动到等号右侧。如下:
SELECT * FROM t2 WHERE score = 10*9
SELECT * FROM t2 WHERE username LIKE 'li%'
7.SQL
学生表:student(学号,学生姓名,出生年月,性别)
成绩表:score(主键,学号,课程号,成绩)
课程表:course(课程号,课程名称,教师号)
教师表:teacher(教师号,教师姓名)
(1)学生表和成绩表的建表语句(根据需求定义字段类型,外键约束等)
create table student(
sid int not null primary key auto_increment,
sname varchar(32) not null,
ctime datetime not null,
gender varchar(8) not null
);
create table score(
id int not null primary key auto_increment,
student_id int,
course_id int,
num int,
constraint fk_score_student foreign (student_id) references student(sid),
constraint fk_score_course foreign (course_id) references course(cid)
);
create table course(
cid int not null primary key auto_increment,
cname varchar(32) not null,
teacher_id int,
constraint fk_course_teacher foreign (teacher_id) references teacher(tid)
);
create table teacher(
tid int not null primary key auto_increment,
tname varchar(32)
);
(2)查姓王的学生名单
select * from student where sname like "王%";
(3)查男同学年龄从小到大排列,第6到第10位同学的所有信息(学生表信息)
select * from student where gender = "F" order by ctime asc;
(4)查姓张老师的个数
select count(*) from teacher where tname like "张%";
(5)查询数学课(课程号001)平均成绩
select avg(score.num) from score
left join course on score.course_id=course.cid
where
course.cid=001
select course_id, avg(num) from score group by course_id having course_id=1;
(6)查每门课程选课人数
select count(*) from score
left join course on score.course_id=course.cid
group by
score.course_cid
select course_id,count(student_id) from score group by course_id;
(7)查各科成绩最高和最低分
select max(num),min(num) from score
left join course on score.course_id=course.cid
group by course_id
select course_id, min(num), max(num) from score group by course_id;
(8)查询课程成绩小于60分学生的学号、姓名
select student.sid,student.sname from score
left join course on score.course_id=course.cid
left join student on score.student_id=student.sid
where
score.num < 60
group by
course.cid
select * from score inner join student on score.student_id=student.sid where score.num>80;