Python操作MySQL

Python 操作 MySQL 的方式

  • 通过 pymysql 模块操作
  • 通过 sqlalchemy ORM 框架操作

pymysql

pymysql 是 python 下操作 mysql 的模块之一,其操作的方法与 MySQLdb 类似

1、下载安装

pip3 install pymysql

2、操作

import pymysql

# 创建连接
connection = pymysql.connect(host='10.211.55.5', port=3306, user='wenchong', password='111111', db='test')
# 创建游标
cursor = connection.cursor()

# 执行SQL语句,effect_row 返回受影响的行数
effect_row1 = cursor.execute("insert into user (username, group_id) values ('testuser', 5)")
effect_row2 = cursor.execute("update user set username = 'test3' where id = %s", (13,))
effect_row3 = cursor.executemany("insert into user (username, group_id) values (%s,%s)", [('test1',3),('test2',4)])

# 获取新添加的最后一条数据中自增的 ID
new_id = cursor.lastrowid

# 执行查询语句
cursor.execute("select * from user")

# 获取第一条数据
row_1 = cursor.fetchone()
print(row_1)

# 获取 N 条数据
row_2 = cursor.fetchmany(5)
print(row_2)

# 获取所有的数据
row_3 = cursor.fetchall()
print(row_3)

# 提交,否则无法保存新建或修改的数据
connection.commit()

# 关闭游标和连接
cursor.close()
connection.close()

通过 fetch 获取 select 的数据时按顺序获取,可以通过 cursor.scroll(num,mode) 来移动游标位置,如:

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

通过 fetch 获取数据时默认是元组类型,如果想要字典类型的数据需要将游标设置为字典类型

connection = pymysql.connect(host='10.211.55.5', port=3306, user='wenchong', password='111111', db='test')

# 设置游标为字典类型
cursor = connection.cursor(cursor=pymysql.cursors.DictCursor)

cursor.execute("select * from user")

row = cursor.fetchmany(5)
print(row)

connection.commit()

cursor.close()
connection.close()

SQLAlchemy

SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

一、安装

pip3 install sqlalchemy

SQLAlchemy 本身无法操作数据库,必须依赖 pymysql 等第三方的模块,Dialect 用于和 DBAPI 进行交流,根据配置文件的不同,从而选择不同的 DBAPI 对数据库进行操作

如:

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/rel_1_1/core/engines.html

二、内部处理

使用 engine/ConnectionPooling/Dialect 进行数据库操作,engine 通过 ConnectionPooling 连接数据库,再通过 Dialect 对数据进行操作

# /user/bin/env python
__author__ = 'wenchong'

from sqlalchemy import create_engine

# max_overflow 最大连接池
engine = create_engine("mysql+pymysql://wenchong:111111@10.211.55.5:3306/test", max_overflow=5)

# 插入数据
cur = engine.execute("insert into user (username, group_id) values ('test4', 3)")
cur1 = engine.execute("insert into user (username, group_id) values (%s,%s), [('test5', 2),('test6', 3)]")

# 获取最后插入的行的自增 id
new_id = cur1.lastrowid

# 执行查询语句
cur2 = engine.execute("select * from user")

# 获取查询结果
row1 = cur2.fetchone()
row2 = cur2.fetchmany(5)
row3 = cur2.fetchall()

三、ORM 功能使用

1、创建表

# /user/bin/env python
__author__ = 'wenchong'


from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("mysql+pymysql://wenchong:111111@10.211.55.5:3306/test", max_overflow=5)

Base = declarative_base()

# 创建单表
class MyTable(Base):
    __tablename__ = 'myTable'

    id = Column(Integer, primary_key=True)
    username = Column(String(32))

    # 当打印一个 Users 对象时,返回该方法
    def __repr__(self):
        return self.username


# 一对多
class Groups(Base):
    __tablename__ = 'groups'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(32))

class Users(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String(32))
    group_id = Column(Integer, ForeignKey('groups.id'))  # 创建主键约束


# 多对多
class Servers(Base):
    __tablename__ = 'servers'

    id = Column(Integer, primary_key=True, autoincrement=True)
    hostname = Column(String(32), nullable=False, unique=True)
    port = Column(Integer, default=22)

class Products(Base):
    __tablename__ = 'products'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False, unique=True)

class ServerToProduct(Base):
    __tablename__ = 'servertogroup'

    id = Column(Integer, primary_key=True, autoincrement=True)
    server_id = Column(Integer, ForeignKey('servers.id'))
    product_id = Column(Integer, ForeignKey('products.id'))


def create_table():
    """创建上面的所有表"""
    Base.metadata.create_all(engine)

def drop_table():
    """删除上面的所有表"""
    Base.metadata.drop_all(engine)


create_table()

2、添加数据

from sqlalchemy.orm import sessionmaker

Session
= sessionmaker(bind=engine) session = Session() # 添加一条数据 obj = MyTable(username='wen1') session.add(obj) # 添加多条数据 session.add_all([ MyTable(username='wen2'), MyTable(username='wen3'), MyTable(username='wen4'), ]) session.commit()

3、删除数据

# 删除 MyTable 表中 id 大于 2 的所有行
session.query(MyTable).filter(MyTable.id > 2).delete()
session.commit()

4、修改数据

session.query(MyTable).filter(MyTable.username == 'wen1').update({'username':'WenChong'})
session.commit()

5、查数据

# MyTable 表中的所有数据,返回值为 list
session.query(MyTable).all()

# 返回指定的列,返回值为 list
session.query(MyTable.id, MyTable.username).all()

# MyTable 表中 id 大于 2 的所有数据,返回值为 list
session.query(MyTable).filter(MyTable.id > 2).all()

# MyTable 表中 id 大于 2 的第一条数据,返回值为 MyTable 对象
session.query(MyTable).filter(MyTable.id > 2).first()
# 条件
ret1 = session.query(MyTable.id, MyTable.username).filter(MyTable.id > 2).all()
ret2 = session.query(MyTable).filter(MyTable.id.between(2,5)).all()
ret3 = session.query(MyTable).filter(MyTable.id.in_([3,4,5])).all()
ret4_not_in = session.query(MyTable).filter(~MyTable.id.in_([3,4,5])).all()
ret4 = session.query(MyTable).filter(MyTable.id.notin_([3,4,5])).all()
ret5 = session.query(MyTable).filter(MyTable.id.in_(session.query(MyTable.id).filter(MyTable.username == 'wen2'))).all()

from sqlalchemy import and_, or_
ret6 = session.query(MyTable.id, MyTable.username).filter(and_(MyTable.id == 5, MyTable.username == 'wen2')).all()
ret7 = session.query(MyTable.id, MyTable.username).filter(or_(MyTable.id == 5, MyTable.username == 'wen2')).all()
ret8 = session.query(MyTable.id, MyTable.username).filter(
    or_(
        MyTable.id == 6,
        and_(MyTable.username == 'wen2', MyTable.id > 10),
    )
).all()

# 通配符
ret1 = session.query(MyTable).filter(MyTable.username.like("wen%")).all()
ret2 = session.query(MyTable).filter(MyTable.username.like("wen_")).all()
ret3 = session.query(MyTable).filter(MyTable.username.notlike("wen%")).all()

# 限制
ret1 = session.query(MyTable)[0:5]

# 排序
ret1 = session.query(MyTable).order_by(MyTable.id.desc()).all()
ret2 = session.query(MyTable).order_by(MyTable.id.desc(), MyTable.username.asc()).all()

# 分组
from sqlalchemy import func

ret1 = session.query(MyTable).group_by(MyTable.username).all()
ret2 = session.query(
    func.sum(MyTable.id),
    func.max(MyTable.id),
    func.min(MyTable.id),
    func.count(MyTable.id),
    MyTable.username).group_by(MyTable.username).all()

ret3 = session.query(
    func.sum(MyTable.id),
    func.max(MyTable.id),
    func.min(MyTable.id),
    func.count(MyTable.id),
    MyTable.username).group_by(MyTable.username).having(func.min(MyTable.id) > 6).all()

# 连表
ret1 = session.query(Users.username,Groups.name).filter(Users.group_id == Groups.id).all()
ret2 = session.query(Users.username,Groups.name).join(Users).all()
ret3 = session.query(Users.username,Groups.name).join(Groups, isouter=True).all()

# 组合
q1 = session.query(Users.username)
q2 = session.query(Groups.name)
ret1 = q1.union(q2).all()
ret2 = q1.union_all(q2).all()

6、配置联系

relationship 用于定义一张表到另外一张表的关系

"""一对多"""

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine("mysql+pymysql://wenchong:111111@10.211.55.5:3306/test", max_overflow=5)

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50))
    addresses = relationship("Address", backref="user")  # 配置关系, backref=user,为在 Address 中也添加 User 的关系

class Address(Base):
    __tablename__ = 'addresses'

    id = Column(Integer, primary_key=True, autoincrement=True)
    email = Column(String(50))
    user_id = Column(Integer, ForeignKey('users.id'))  # 设置主键约束

# 创建表
Base.metadata.create_all(engine)

# 创建 session
Session =sessionmaker(bind=engine)
session = Session()

# 添加数据
eric = User(
    name='eric',
    addresses = [
        Address(email='eric1@126.com'),
        Address(email='eric2@126.com'),
    ]
    )

session.add(eric)
session.commit()

# 使用 join 查询数据
# 通过 address 查 user
ret = session.query(Address).join(User).filter(Address.user_id == User.id).filter(
    User.name == 'eric').all()
for item in ret:
    print(item.email)

# 通过 user 查 email
ret1 = session.query(User).join(Address).filter(Address.user_id == User.id).filter(
    Address.email.like('eric1%')).all()
for item in ret1:
    print(item.name)

# 使用关系查询数据
# 通过 user 查看 email
user_obj = session.query(User).filter(User.name == 'eric').one()
for obj in user_obj.addresses:
    print(obj.email)

# 通过 email 查看 user
email_obj = session.query(Address).filter(Address.email.like('eric1%')).one()
print(email_obj.user.name)
"""多对多"""

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, ForeignKeyConstraint, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine("mysql+pymysql://wenchong:111111@10.211.55.5:3306/test", max_overflow=5)

Base = declarative_base()


class PageToTag(Base):
    __tablename__ = 'pagetotag'
    id = Column(Integer, primary_key=True, autoincrement=True)
    page_id = Column(Integer, ForeignKey('page.id'))
    tag_id = Column(Integer, ForeignKey('tag.id'))


class Page(Base):
    __tablename__ = 'page'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64))
    tags = relationship('Tag', secondary=PageToTag.__table__)


class Tag(Base):
    __tablename__ = 'tag'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(32))
    pages = relationship('Page', secondary=PageToTag.__table__)

# 创建表
Base.metadata.bind = engine
Base.metadata.create_all()

# 创建session
Session =sessionmaker(bind=engine)
session = Session()

# 添加数据
page = Page(name='Python API Page')
python_tag = Tag(name='Python')
api_tag = Tag(name='API')

page.tags.append(api_tag)
page.tags.append(python_tag)

session.add(page)
session.commit()

# 查询数据
page_obj = session.query(Page).filter(Page.name == 'Python API Page').one()
print([t.name for t in page_obj.tags])

7、aliases

当查询时需要涉及到多个表,当同一张表出现多次时,为了避免冲突,使用 aliases 为表创建一个别名

from sqlalchemy.orm import aliased

aliases1 = aliased(Address)
aliases2 = aliased(Address)

for u, e1, e2 in session.query(User.name, aliases1.email, aliases2.email).join(
        aliases1, User.addresses).join(
        aliases2, User.addresses).filter(
                aliases1.email == 'eric1@126.com').filter(
                aliases2.email == 'eric2@126.com'):
    print(u, e1, e2)

 

posted @ 2016-10-18 18:06  wenchong  阅读(248)  评论(0编辑  收藏  举报