安装MySQLdb
MySQLdb 是用于Python链接Mysql数据库的接口,如果是windows系统:登录https://pypi.python.org/pypi/MySQL-python/1.2.5找到.exe结尾的包,直接安装即可
以下界面即代表成功安装
如果是linux或者其他系统,可以下载源码包进行安装:上节链接中的zip包,然后安装:
yum install –y python-devel yum install –y mysql-devel yum install –y gcc unzip MySQL-python-1.2.5.zip cd MySQL-python-1.2.5 python setup.py build python setup.py install
数据库连接
MySQLdb提供了connect方法用来和数据库建立连接,接收数个参数,返回连接对象:
代码如下:
首先在mysql的数据库中建立python库:create database python;
conn=MySQLdb.connect(host="192.168.48.128",user="xiang",passwd="123456",db="python",charset="utf8")
比较常用的参数包括:
host:数据库主机名.默认是用本地主机
user:数据库登陆名.默认是当前用户
passwd:数据库登陆的秘密.默认为空
db:要使用的数据库名.没有默认值
port:MySQL服务使用的TCP端口.默认是3306,数字类型
charset:数据库编码
更多关于参数的信息可以查这里 http://mysql-python.sourceforge.net/MySQLdb.html
有时候,为了我们代码的规范,我更加推荐把所有数据库的配置写在一个字典中
import MySQLdb #连接数据库 # host 数据库ip # port 数据库端口 # user 连接数据库用户 # passwd 用户密码 # db 数据库名字 # charset 字符集 utf-8 import MySQLdb conn=MySQLdb.connect(host="192.168.214.26",user="bigk",passwd="123456",db="bigk",charset="utf8") def connect_mysql(): db_config={ "host":"192.168.214.26", "port":3306, "user":"bigk", "passwd":"123456", "db":"bigk", "charset":"utf8" } cnx=MySQLdb.connect(**db_config) return cnx print(connect_mysql())
Mysql事务
在讲游标之前,我们先来了解什么是mysql的事物。这对游标的理解非常有帮助。
mysql事务
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如,你操作一个数据库,公司的一个员工离职了,你要在数据库中删除他的资料,也要删除该人员相关的,比如邮箱,个人资产等。这些数据库操作语言就构成了一个事务。
在MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务,所以很多情况下我们都使用innodb引擎。
事务处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么全部不执行。
一般来说,事务是必须满足4个条件(ACID): Atomicity(原子性)、Consistency(稳定性)、Isolation(隔离性)、Durability(可靠性)
1、事务的原子性:一组事务,要么成功;要么撤回。
2、稳定性 : 有非法数据(外键约束之类),事务撤回。
3、隔离性:事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
4、可靠性:软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit选项 决定什么时候吧事务保存到日志里。
而mysql在默认的情况下,他是把每个select,insert,update,delete等做为一个事务的,登录mysql服务器,进入mysql,执行以下命令:
mysql> show variables like 'auto%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| autocommit | ON |
| automatic_sp_privileges | ON |
+--------------------------+-------+
4 rows in set (0.00 sec)
如上所示: 有一个参数autocommit就是自动提交的意思,每执行一个msyql的select,insert,update等操作,就会进行自动提交。
如果把改选项关闭,我们就可以每次执行完一次代码就需要进行手动提交,connect对象给我们提供了两种办法来操作提交数据。
mysql事务的方法
commit():提交当前事务,如果是支持事务的数据库执行增删改后没有commit则数据库默认回滚,相当于删除了之前的操作。默认自动开启了autocommit功能
rollback():取消当前事务
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', 'charset': 'utf8' } cnx = MySQLdb.connect(**db_config) return cnx if __name__ == '__main__': cnx = connect_mysql() cus = cnx.cursor() sql = "create table test(id int not null);insert into test(id) values (100);" try: cus.execute(sql) cus.close() cnx.commit() except Exception as e: # cnx.rollback() # print('Error') raise e finally: cnx.close()
表结构设计
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', 'charset': 'utf8' } cnx = MySQLdb.connect(**db_config) return cnx if __name__ == '__main__': cnx = connect_mysql() cus = cnx.cursor() # sql = "create table test(id int not null);insert into test(id) values (100);" # student = ''' # create table student( # StdID int not null primary key. # StdNAME varchar(100) not null, # Gender enum('M','F'), # age tinyint # ); # ''' student = '''create table student( StdID int not null primary key auto_increment, StdName varchar(100) not null, Gender enum('M', 'F'), Age tinyint )''' course = '''create table Course( CouID int not null, CName varchar(50) not null, TID int not null )''' score = '''create table Score( SID int not null, StdID int not null, CID int not null, Grade int not null )''' teacher = '''create table Teacher( TID int not null, TName varchar(100) not null )''' tmp = '''set @i := 0; create table tmp as select (@i := @i + 1) as id from information_schema.tables limit 10; ''' try: cus.execute(student) cus.execute(course) cus.execute(score) cus.execute(teacher) cus.execute(tmp) cus.close() cnx.commit() # try: # cus.execute(student) # cus.close() # cnx.commit() except Exception as e: cnx.rollback() # print('Error') raise e finally: cnx.close()
创建表
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', 'charset': 'utf8' } cnx = MySQLdb.connect(**db_config) return cnx if __name__ == '__main__': cnx = connect_mysql() cus = cnx.cursor() # sql = "create table test(id int not null);insert into test(id) values (100);" # student = ''' # create table student( # StdID int not null primary key. # StdNAME varchar(100) not null, # Gender enum('M','F'), # age tinyint # ); # ''' student = '''create table student( StdID int not null primary key auto_increment, StdName varchar(100) not null, Gender enum('M', 'F'), Age tinyint )''' course = '''create table Course( CouID int not null, CName varchar(50) not null, TID int not null )''' score = '''create table Score( SID int not null, StdID int not null, CID int not null, Grade int not null )''' teacher = '''create table Teacher( TID int not null, TName varchar(100) not null )''' tmp = '''set @i := 0; create table tmp as select (@i := @i + 1) as id from information_schema.tables limit 10; ''' try: cus.execute(student) cus.execute(course) cus.execute(score) cus.execute(teacher) cus.execute(tmp) cus.close() cnx.commit() # try: # cus.execute(student) # cus.close() # cnx.commit() except Exception as e: cnx.rollback() # print('Error') raise e finally: cnx.close()
增加数据
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', 'charset': 'utf8' } cnx = MySQLdb.connect(**db_config) return cnx if __name__ == '__main__': cnx = connect_mysql() students = '''set @i := 10000; insert into Student select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 3 + floor(rand() * 75)), case floor(rand()*10) mod 2 when 1 then 'M' else 'F' end, 25-floor(rand() * 5) from tmp a, tmp b, tmp c, tmp d; ''' course = '''set @i := 10; insert into Course select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 5 + floor(rand() * 40)), 1 + floor(rand() * 100) from tmp a; ''' score = '''set @i := 10000; insert into Score select @i := @i +1, floor(10001 + rand()*10000), floor(11 + rand()*10), floor(1+rand()*100) from tmp a, tmp b, tmp c, tmp d; ''' theacher = '''set @i := 100; insert into Teacher select @i:=@i+1, substr(concat(sha1(rand()), sha1(rand())), 1, 5 + floor(rand() * 80)) from tmp a, tmp b; ''' try: cus_students = cnx.cursor() cus_students.execute(students) cus_students.close() cus_course = cnx.cursor() cus_course.execute(course) cus_course.close() cus_score = cnx.cursor() cus_score.execute(score) cus_score.close() cus_teacher = cnx.cursor() cus_teacher.execute(theacher) cus_teacher.close() cnx.commit() except Exception as e: cnx.rollback() print('error') raise e finally: cnx.close()
查询数据
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', 'charset': 'utf8' } cnx = MySQLdb.connect(**db_config) return cnx if __name__ == '__main__': cnx = connect_mysql() sql = '''select * from Student where StdName in (select StdName from Student group by StdName having count(1)>1 ) order by StdName;''' try: cus = cnx.cursor() cus.execute(sql) result = cus.fetchall() with codecs.open('select.txt', 'w+') as f: for line in result: f.write(str(line)) f.write(' ') cus.close() cnx.commit() except Exception as e: cnx.rollback() print('error') raise e finally: cnx.close()
删除数据
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', '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()
更新数据
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', '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()
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) 的索引来使用。
import MySQLdb def connect_mysql(): db_config = { 'host': '192.168.214.26', 'port': 3306, 'user': 'bigk', 'passwd': '123456', 'db': 'bigk', '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()
主键和索引的区别
1. 主键一定是唯一性索引,唯一性索引并不一定就是主键。 所谓主键就是能够唯一标识表中某一行的属性或属性组,一个表只能有一个主键,但可以有多个候选索引。因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。数据库在设计时,主键起到了很重要的作用。 主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,所以主键也是一个特殊的索引。 2. 一个表中可以有多个唯一性索引,但只能有一个主键。 3. 主键列不允许空值,而唯一性索引列允许空值。 5. 索引可以提高查询的速度。 创建Course的CouID的字段为主键 Score的SID字段为主键 Student的StdID字段为主键 Teacher的TID字段为主键