本篇对于Python操作MySQL主要使用两种方式:

  • 原生模块 pymsql

  • ORM框架 SQLAchemy

pymsql

pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同。

下载安装

pip3 install pymysql

使用操作

1、执行SQL

# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db1',charset='utf8')
# 创建游标
cursor = conn.cursor() # 执行SQL,并返回受影响行数
effect_row = cursor.execute("update hosts set host = '1.1.1.2' where nid > %s", (1,)) # 执行SQL,并返回受影响行数
effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)]) # 提交,不然无法保存新建或者修改的数据
conn.commit() # 关闭游标
cursor.close()
# 关闭连接
conn.close()

增,删,改需要执行 conn.commit()

2、获取新创建数据自增ID

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
cursor = conn.cursor()
cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)])
conn.commit()
cursor.close()
conn.close() # 获取最新自增ID => 如果插入多条,只能拿到最后一条id
new_id = cursor.lastrowid

3、获取查询数据

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
cursor = conn.cursor()
cursor.execute("select * from hosts") # 获取第一行数据
row_1 = cursor.fetchone()
# => 再次执行:cursor.fetchone() 获得下一条数据,没有时为None # 获取前n行数据
# row_2 = cursor.fetchmany(n)
# ==> 执行了n次fetchone() # 获取所有数据
# row_3 = cursor.fetchall() conn.commit()
cursor.close()
conn.close()

注:在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置,如:

  • cursor.scroll(-1,mode='relative')  # 相对当前位置移动

  • cursor.scroll(2,mode='absolute') # 相对绝对位置移动

4、fetch数据类型

  关于默认获取的数据是元祖类型,如果想要或者字典类型的数据,即:

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='t1')

# 游标设置为字典类型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) row = cursor.execute("select * from user") result = cursor.fetchone()
print(result) conn.commit()
cursor.close()
conn.close()

补充:

1.SQL注入

由于字符串拼接出现注入
"select name from user where name='%s' and password ='%s' " %(username,password)
pymysql 提供了转义功能:
"select name from user where name=%s and password =%s ",( username,password ) 

SQLAchemy

SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,

简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

ORM:

ORM框架的作用就是把数据库表的一行记录与一个对象互相做自动转换。 正确使用ORM的前提是了解关系数据库的原理。

ORM就是把数据库表的行与相应的对象建立关联,互相转换。 由于关系数据库的多个表还可以用外键实现一对多、多对多等关联,

相应地, ORM框架也可以提供两个对象之间的一对多、多对多等功能。

SQLAlchemy:

本身无法操作数据库,其必须以pymsql等第三方插件,

Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

MySQL-Python
mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql
mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] MySQL-Connector
mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> cx_Oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
#!/usr/bin/env python
# -*-coding:utf-8 -*- from sqlalchemy import create_engine,and_,or_,func,Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/t1?charset=utf8", max_overflow=5) Base = declarative_base() def init_db():
Base.metadata.create_all(engine) def drop_db():
Base.metadata.drop_all(engine)

一、底层处理

使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5) # 执行SQL
# cur = engine.execute(
# "INSERT INTO hosts (host, color_id) VALUES ('1.1.1.22', 3)"
# ) # 新插入行自增ID
# cur.lastrowid # 执行SQL
# cur = engine.execute(
# "INSERT INTO hosts (host, color_id) VALUES(%s, %s)",[('1.1.1.22', 3),('1.1.1.221', 3),]
# ) # 执行SQL
# cur = engine.execute(
# "INSERT INTO hosts (host, color_id) VALUES (%(host)s, %(color_id)s)",
# host='1.1.1.99', color_id=3
# ) # 执行SQL
# cur = engine.execute('select * from hosts')
# 获取第一行数据
# cur.fetchone()
# 获取第n行数据
# cur.fetchmany(3)
# 获取所有数据
# cur.fetchall()

二、ORM功能使用

使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。

根据类创建对象,对象转换成SQL,执行SQL。处理中文数据时,在连接数据库时要加上   ?charset=utf8

1.创建表

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5) Base = declarative_base() # 创建单表
class Users(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True)
name = Column(String(32))
extra = Column(String(16)) # 设置索引:
__table_args__ = (
UniqueConstraint('id', 'name', name='uix_id_name'),
Index('ix_id_name', 'name', 'extra'),
) # 输出Users对象时,调用:
def __repr__(self):
return "%s-%s-%s" % (self.id, self.name , self.extra) def init_db():
Base.metadata.create_all(engine) #创建表 def drop_db():
Base.metadata.drop_all(engine) #删除表

一对多

# 一对多
class Favor(Base):
__tablename__ = 'favor'
nid = Column(Integer, primary_key=True)
caption = Column(String(50), default='red', unique=True) class Person(Base):
__tablename__ = 'person'
nid = Column(Integer, primary_key=True)
name = Column(String(32), index=True, nullable=True)
favor_id = Column(Integer, ForeignKey("favor.nid")) # 外键

多对多

# 多对多
class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
name = Column(String(64), unique=True, nullable=False)
port = Column(Integer, default=22) class Server(Base):
__tablename__ = 'server' id = Column(Integer, primary_key=True, autoincrement=True)
hostname = Column(String(64), unique=True, nullable=False) class ServerToGroup(Base):
__tablename__ = 'servertogroup'
nid = Column(Integer, primary_key=True, autoincrement=True)
server_id = Column(Integer, ForeignKey('server.id'))
group_id = Column(Integer, ForeignKey('group.id'))

2.操作表

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5) #生成一个SQLORM基类
Base = declarative_base() # 创建单表
class Users(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(32))
extra = Column(String(16)) __table_args__ = (
UniqueConstraint('id', 'name', name='uix_id_name'),
Index('ix_id_name', 'name', 'extra'),
) def __repr__(self):
return "%s-%s" %(self.id, self.name) # 一对多
class Favor(Base):
__tablename__ = 'favor'
nid = Column(Integer, primary_key=True)
caption = Column(String(50), default='red', unique=True) def __repr__(self):
return "%s-%s" %(self.nid, self.caption) class Person(Base):
__tablename__ = 'person'
nid = Column(Integer, primary_key=True)
name = Column(String(32), index=True, nullable=True)
favor_id = Column(Integer, ForeignKey("favor.nid"))
# 与生成表结构无关,仅用于查询方便
favor = relationship("Favor", backref='pers') # 多对多
class ServerToGroup(Base):
__tablename__ = 'servertogroup'
nid = Column(Integer, primary_key=True, autoincrement=True)
server_id = Column(Integer, ForeignKey('server.id'))
group_id = Column(Integer, ForeignKey('group.id'))
group = relationship("Group", backref='s2g')
server = relationship("Server", backref='s2g') class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
name = Column(String(64), unique=True, nullable=False)
port = Column(Integer, default=22)
# group = relationship('Group',secondary=ServerToGroup,backref='host_list') class Server(Base):
__tablename__ = 'server' id = Column(Integer, primary_key=True, autoincrement=True)
hostname = Column(String(64), unique=True, nullable=False) def init_db():
Base.metadata.create_all(engine) def drop_db():
Base.metadata.drop_all(engine) # 这两行触发sessionmaker类下的__call__方法,return得到 Session实例,赋给变量session,
# 所以session可以调用Session类下的add,add_all等方法 Session = sessionmaker(bind=engine)
session = Session()

.增

obj = Users(name="alex0", extra='sb')
session.add(obj)
session.add_all([
Users(name="alex1", extra='sb'),
Users(name="alex2", extra='sb'),
]) session.commit()

.删

session.query(Users).filter(Users.id > 2).delete()
session.commit()

.改

session.query(Users).filter(Users.id > 2).update({"name" : ""})
session.query(Users).filter(Users.id > 2).update({Users.name: Users.name + ""}, synchronize_session=False)
session.query(Users).filter(Users.id > 2).update({"num": Users.num + 1}, synchronize_session="evaluate")
session.commit()

.查

ret = session.query(Users).all()
ret = session.query(Users.name, Users.extra).all()
ret = session.query(Users).filter_by(name='alex').all()
ret = session.query(Users).filter_by(name='alex').first()

3.更多查询方法:

#!/usr/bin/env python
# -*-coding:utf-8 -*- from sqlalchemy import create_engine,and_,or_,func,Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship engine = create_engine('mysql+pymysql://root@127.0.0.1:3307/day40?charset=utf8') Base = declarative_base() class Man_To_Woman(Base): __tablename__ = 'man_to_woman'
nid = Column(Integer,primary_key=True)
man_id = Column(Integer,ForeignKey('man.nid'))
woman_id = Column(Integer,ForeignKey('woman.nid')) class Man(Base): __tablename__ = 'man'
nid = Column(Integer,primary_key=True)
name = Column(String(20),nullable=False)
woman = relationship("Woman", secondary=Man_To_Woman.__table__) class Woman(Base): __tablename__ = 'woman'
nid = Column(Integer,primary_key=True)
name = Column(String(20),nullable=False)
man = relationship("Man",secondary=Man_To_Woman.__table__) Base.metadata.create_all(engine) MySession = sessionmaker(engine)
session = MySession()

事例: 表结构

1.filter_by( ... )  填写键值对方式

ret = session.query(Man).filter_by(name='alex').first()
print(ret.nid,ret.name)

2.filter    填写条件判断

ret = session.query(Man).filter(Man.name=='eric').first()

ret = session.query(Man).filter(Man.name=='eric' , Man.nid > 0).first()

row = session.query(Man).filter(Man.nid.between(1,4)).all()

ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()

3.and_  or_  条件判断

from sqlalchemy import and_, or_

ret = session.query(Man).filter(and_(Man.name == 'eric',Man.nid == 2)).first()
ret = session.query(Man).filter(or_(Man.name == 'eric',Man.nid == 2)).first()

4.~   取反

ret = session.query(Man).filter(Man.nid.in_([2,3])).first()
ret = session.query(Man).filter(~Man.nid.in_([2,3])).first()

5.like + %   通配符

ret = session.query(Man).filter(Man.name.like('%x')).first()
ret = session.query(Man).filter(~Man.name.like('%x')).first()

6.切片  限制 ( 序号,前闭后开 )

row = session.query(Man)[1:3]
for ret in row:
print(ret.nid, ret.name) row = session.query(Man).limit(3).offset(1)

7.order_by   排序

row = session.query(Man).order_by(Man.nid.desc()).all()
row = session.query(Man).order_by(Man.nid.asc()).all()

8.group_by  分组

row = session.query(func.count('*')).select_from(Man).all()
row = session.query(func.count('*')).filter(Man_To_Woman.nid > 1).all()
row = session.query(func.count('*')).select_from(Man_To_Woman).group_by(Man_To_Woman.man_id).all()
row = session.query(func.count('*')).select_from(Man_To_Woman).group_by(Man_To_Woman.man_id).limit(1).all() row = session.query(Man_To_Woman).group_by(Man_To_Woman.man_id).all() ret = session.query(Users).group_by(Users.extra).all()
ret = session.query(
func.max(Users.id),
func.sum(Users.id),
func.min(Users.id)).group_by(Users.name).all() ret = session.query(
func.max(Users.id),
func.sum(Users.id),
func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all()

9.join  连表

row = session.query(Users, Favor).filter(Users.id == Favor.nid).all()

ret = session.query(Son).join(Father).all()

ret = session.query(Son).join(Father, isouter=True).all()

10.union  组合

q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union(q2).all() q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union_all(q2).all()

更多功能参见文档,猛击这里下载PDF

补充  Relationship:

  • 改变数据输出的方式:可以在表的类中定义一个特殊成员:__repr__, return一个自定义的由字符串拼接的数据连接方式.

  • 数据库中表关系之间除了MySQL中标准的外键(ForeignKey)之外,还可以创建一个虚拟的关系,比如 group = relationship("Group",backref='uuu'),一般此虚拟关系与foreignkey一起使用.

relationship : 通过relatioinship 找到绑定关系的数据 !!!

一对多,连表操作:

class Father(Base):

    __tablename__ ='father'
nid = Column(Integer,primary_key=True)
name = Column(String(32))
son = relationship('Son') class Son(Base): __tablename__ = 'son'
nid = Column(Integer, primary_key=True)
name = Column(String(32))
father_id = Column(Integer,ForeignKey('father.nid'))
father = relationship('Father')

表结构

正向查询:

需求:查询Son表中所有数据,并且显示对应的Father表中的数据.

ret = session.query(Son).all()
for obj in ret:
print(obj.nid,obj.name,obj.father_id,obj.father.name)

反向查询:

需求:查询Father表中, 属于 alvin 的所有儿子Son.

obj = session.query(Father).filter(Father.name=='alvin').first()

row = obj.son
for ret in row:
print(ret.nid,ret.name,ret.father.name)

多对多,连表操作:

#!/usr/bin/env python
# -*-coding:utf-8 -*- from sqlalchemy import create_engine,and_,or_,func,Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship engine = create_engine('mysql+pymysql://root@127.0.0.1:3307/day40?charset=utf8') Base = declarative_base() class Man_To_Woman(Base): __tablename__ = 'man_to_woman'
nid = Column(Integer,primary_key=True)
man_id = Column(Integer,ForeignKey('man.nid'))
woman_id = Column(Integer,ForeignKey('woman.nid')) class Man(Base): __tablename__ = 'man'
nid = Column(Integer,primary_key=True)
name = Column(String(20),nullable=False)
woman = relationship("Woman", secondary=Man_To_Woman.__table__) class Woman(Base): __tablename__ = 'woman'
nid = Column(Integer,primary_key=True)
name = Column(String(20),nullable=False)
man = relationship("Man",secondary=Man_To_Woman.__table__) Base.metadata.create_all(engine) MySession = sessionmaker(engine)
session = MySession()

表结构

正,反向操作:

1.alex的所有女人

2.凤姐的所有男人

man1 = session.query(Man).filter(Man.name=='alex').first()
print(man1)
for ret in man1.woman:
print(ret.nid,ret.name) woman1 = session.query(Woman).filter(Woman.name=='fengjie').first()
print(woman1)
for ret in woman1.man:
print(ret.nid,ret.name)

relatioinship 语句的简写:  ,我添加到Man表中

woman = relationship("Woman", secondary=Man_To_Woman.__table__,backref='man')

1   关于 session.add   session.query   session.commit的顺序问题?

在同一个会话中, insert into table (xxxx)后,可以接着 select * from xxx; 查询到刚刚插入的数据;

只是不能在其他会话,比如我另开一个客户端去连接数据库不能查询到刚刚插入的数据。

这个数据已经到数据库。值是数据库吧这个数据给锁了。只有插入数据的那个session可以查看到,其他的session不能查看到,可以理解提交并解锁吧。

【Python之路】第十九篇--Python操作MySQL的更多相关文章

  1. Python之路(第二十九篇) 面向对象进阶:内置方法补充、异常处理

    一.__new__方法 __init__()是初始化方法,__new__()方法是构造方法,创建一个新的对象 实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法 __ ...

  2. Python之路(第十九篇)hashlib模块

    一.hashlib模块 HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值 ...

  3. Python开发【第十九篇】:Python操作MySQL

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...

  4. Python之路(第二十四篇) 面向对象初级:多态、封装

    一.多态 多态 多态:一类事物有多种形态,同一种事物的多种形态,动物分为鸡类,猪类.狗类 例子 import abc class H2o(metaclass=abc.ABCMeta): ​ def _ ...

  5. Python之路(第十五篇)sys模块、json模块、pickle模块、shelve模块

    一.sys模块 1.sys.argv 命令行参数List,第一个元素是程序本身路径 2.sys.exit(n) 退出程序,正常退出时exit(0) 3.sys.version . sys.maxint ...

  6. Python之路(第十二篇)程序解耦、模块介绍\导入\安装、包

    一.程序解耦 解耦总的一句话来说,减少依赖,抽象业务和逻辑,让各个功能实现独立. 直观理解“解耦”,就是我可以替换某个模块,对原来系统的功能不造成影响.是两个东西原来互相影响,现在让他们独立发展:核心 ...

  7. 【Python之路】第六篇--Python基础之模块

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...

  8. Python之路(第二十八篇) 面向对象进阶:类的装饰器、元类

    一.类的装饰器 类作为一个对象,也可以被装饰. 例子 def wrap(obj): print("装饰器-----") obj.x = 1 obj.y = 3 obj.z = 5 ...

  9. Python之路(第二十六篇) 面向对象进阶:内置方法

    一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__g ...

随机推荐

  1. JavaScript中使用JSON,即JS操作JSON总结

    JSON(JavaScript Object Notation 对象标记) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生 ...

  2. idea 编程字体推荐

    monaco vardana fira code mediu dejavu sans mono 上述字体 在14号字 1.1倍行距 时编程比较舒服

  3. Xcode5下使用纯代码构建简单的HelloWorld程序

    转自:http://blog.csdn.net/developerxyf/article/details/12874935 新发布的Xcode5在使用模板创建工程的时候取消了以往是否要选择storyb ...

  4. android跨进程通信(IPC)——AIDL

    转载请标明出处: http://blog.csdn.net/sinat_15877283/article/details/51026711: 本文出自: [温利东的博客] 近期在看 @任玉刚 大神编写 ...

  5. jQuery 实战读书笔记之第六章:事件本质

    理解浏览器事件模型 understandEventModel.html 代码: <!DOCTYPE HTML> <html> <head> <title> ...

  6. iReport4.6.0图表操作

    做报表.图表肯定是少不了的.尽管是疲惫的周一工作还是要做啊... 第一步:创建一个新的空白项目,数据源创建这个网上非常多资料,不是本章重点就不再详述 第二步:iReport界面,窗体->组件面板 ...

  7. Mock数据使用的Util

    package com.xxx.common.util; import java.lang.reflect.Field; import java.lang.reflect.Method; import ...

  8. 一行python打印乘法表

    一行代码打印乘法表 >>> print '\n'.join([' '.join(['%s*%s=%-2s' %(y,x,x*y) for y in range(1,x+1)]) fo ...

  9. 判断下列语句是否正确,如果有错误,请指出错误所在?interface A{

    判断下列语句是否正确,如果有错误,请指出错误所在? interface A{ int add(final A a); } class B implements A{ long add(final A ...

  10. CH Round #55 - Streaming #6 (NOIP模拟赛day2)(被虐哭)

    http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20%28NOIP%E6%A8%A1%E6%8B%9F%E8%B ...