今日任务:
六周四次课(11月23日)
12.12/12.13 删除数据
12.14 更改数据
12.15 索引
笔记:
删除数据
有些老师不好好上次,导致课程的及格率太低,最后名最差的5名老师将会被开除。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : lingxiangxiang
# @File : delete.py
import codecs
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
sql = '''delete from Teacher where TID in(
select TID from (select Course.CouID, Course.TID, Teacher.TName, count(Teacher.TID) as count_teacher from Course
left join Score on Score.Grade < 60 and Course.CouID = Score.CouID
left join Teacher on Course.TID = Teacher.TID
group by Course.TID
order by count_teacher desc
limit 5) as test )
'''
try:
cus = cnx.cursor()
cus.execute(sql)
result = cus.fetchall()
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
结果:
程序正常执行,没有报错
解释:
- 先查询出Course表中的Course.TID和Course.TID
- left join 是关联Score表,查出Score.Grade > 59,并且,课程ID和课程表的CouID要对应上
- left join Teacher 是关联老师表,课程中的了老师ID和老师表中的老师ID对应上
- select中加上老师的名字Teacher.Tname和count(Teacher.TID)
- group by Course.TID,在根据老师的的TID进行分组
- oder by 最后对count_teacher进行排序,取前5行,
- 在通过套用一个select子查询,把所有的TID搂出来
- 然后delete from Teacher 最后删除TID在上表中的子查询中。
修改数据
首先,我们把分数低于5分的成绩所有都加60分。
代码如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : lingxiangxiang
# @File : update.py
import codecs
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
sql = '''select *, (grade+60) as newGrade from Score where Grade <5;'''
update = '''update Score set grade = grade + 60 where grade < 5; '''
try:
cus_start = cnx.cursor()
cus_start.execute(sql)
result1 = cus_start.fetchall()
print(len(result1))
cus_start.close()
cus_update = cnx.cursor()
cus_update.execute(update)
cus_update.close()
cus_end = cnx.cursor()
cus_end.execute(sql)
result2 = cus_end.fetchall()
print(len(result2))
cus_end.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
结果:
321
0
解释:
1.刚开始,我们可以查到分数小于5分的总个数有321个
2.select *, (grade+60) as newGrade from Score where Grade <5;这个sql是把所有的成绩小于5的都列出来,然后最后加一列分数加60分的结果。
3.update Score set grade = grade + 60 where grade < 5;是把分数小于5的所有成绩都加60分
4.最后在检查分数小于5的个数为0,说明所有低于5分的分数都发生了改变。
索引
MySQL索引的概念
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。
索引类别
1.普通索引
普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column =)或排序条件(ORDER BY column)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
2.唯一索引
普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个“员工个人资料”数据表里可能出现两次或更多次。
如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE 把它定义为一个唯一索引。这么做的好处:一是简化了 MySQL 对这个索引的管理工作,这个索引也因此而变得更有效率;二是 MySQL 会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;如果是,MySQL 将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。
3.主索引
在前面已经反复多次强调过:必须为主键字段创建一个索引,这个索引就是所谓的“主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是 PRIMARY 而不是 UNIQUE。
4.外键索引
如果为某个外键字段定义了一个外键约束条件,MySQL 就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。
5.复合索引
索引可以覆盖多个数据列,如像 INDEX (columnA, columnB) 索引。这种索引的特点是 MySQL 可以有选择地使用一个这样的索引。如果查询操作只需要用到 columnA 数据列上的一个索引,就可以使用复合索引 INDEX(columnA, columnB)。不过,这种用法仅适用于在复合索引中排列在前的数据列组合。比如说,INDEX (A,B,C) 可以当做 A 或 (A,B) 的索引来使用,但不能当做 B、C 或 (B,C) 的索引来使用。
mysql主键和索引的区别:
1. 主键一定是唯一性索引,唯一性索引并不一定就是主键。
所谓主键就是能够唯一标识表中某一行的属性或属性组,一个表只能有一个主键,但可以有多个候选索引。因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。数据库在设计时,主键起到了很重要的作用。
主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,所以主键也是一个特殊的索引。
2. 一个表中可以有多个唯一性索引,但只能有一个主键。
3. 主键列不允许空值,而唯一性索引列允许空值。
- 索引可以提高查询的速度。
创建Course的CouID的字段为主键 Score的SID字段为主键 Student的StdID字段为主键 Teacher的TID字段为主键,
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : lingxiangxiang
# @File : keys.py
import codecs
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
sql1 = '''alter table Teacher add primary key(TID);'''
sql2 = '''alter table Student add primary key(StdID);'''
sql3 = '''alter table Score add primary key(SID);'''
sql4 = '''alter table Course add primary key(CouID);'''
sql5 = '''alter table Score add index idx_StdID_CouID(StdID, CouID);'''
# sql6 = '''alter table Score drop index idx_StdID_CouID;''' 删除索引
sql7 = '''explain select * from Score where StdID = 16213;'''
try:
cus = cnx.cursor()
cus.execute(sql1)
cus.close()
cus = cnx.cursor()
cus.execute(sql2)
cus.close()
cus = cnx.cursor()
cus.execute(sql3)
cus.close()
cus = cnx.cursor()
cus.execute(sql4)
cus.close()
cus = cnx.cursor()
cus.execute(sql5)
cus.close()
cus = cnx.cursor()
cus.execute(sql7)
result = cus.fetchall()
print(result)
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
结果:
((1L, u'SIMPLE', u'Score', u'ref', u'idx_StdID_CouID', u'idx_StdID_CouID', u'4', u'const', 4L, None),)
解释:
Sql1, sql2, sql3, sql4是添加主键,sql5是增加一个索引,我们也可以在mysql的客户端上执行sq7,得到如下的结果:
mysql> explain select * from Score where StdID = 16213;
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------+
| 1 | SIMPLE | Score | ref | idx_StdID_CouID | idx_StdID_CouID | 4 | const | 4 | NULL |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------+
1 row in set (0.00 sec)
这个说明,我们在搜索StdID的时候,是走了idx_StdID_CouID索引的。