Python操作MySQL数据库的三个模块

​python使用MySQL主要有两个模块,pymysql(MySQLdb)和SQLAchemy。

为信阳等地区用户提供了全套网页设计制作服务,及信阳网站建设行业解决方案。主营业务为成都网站制作、网站建设、信阳网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

  • pymysql(MySQLdb)为原生模块,直接执行sql语句,其中pymysql模块支持python 2和python3,MySQLdb只支持python2,两者使用起来几乎一样。
  • SQLAchemy为一个ORM框架,将数据对象转换成SQL,然后使用数据API执行SQL并获取执行结果
  • 另外DBUtils模块提供了一个数据库连接池,方便多线程场景中python操作数据库。

1.pymysql模块

安装:pip install pymysql

创建表格操作(注意中文格式设置)

#coding:utf-8
import pymysql

#关于中文问题
#1. mysql命令行创建数据库,设置编码为gbk:create databse demo2 character set utf8;
#2. python代码中连接时设置charset="gbk"
#3. 创建表格时设置default charset=utf8

#连接数据库
conn = pymysql.connect(host="localhost", user="root", passwd="", db='learningsql', charset='utf8', port=3306) #和mysql服务端设置格式一样(还可设置为gbk, gb2312)
#创建游标
cursor = conn.cursor()
#执行sql语句
cursor.execute("""create table if not exists t_sales(
id int primary key auto_increment not null,
nickName varchar(128) not null,
color varchar(128) not null,
size varchar(128) not null,
comment text not null,
saledate varchar(128) not null)engine=InnoDB default charset=utf8;""")

# cursor.execute("""insert into t_sales(nickName,color,size,comment,saledate)
# values('%s','%s','%s','%s','%s');""" % ("zack", "黑色", "L", "大小合适", "2019-04-20"))

cursor.execute("""insert into t_sales(nickName,color,size,comment,saledate)
values(%s,%s,%s,%s,%s);""" , ("zack", "黑色", "L", "大小合适", "2019-04-20"))
#提交
conn.commit()
#关闭游标
cursor.close()
#关闭连接
conn.close()

增删改查:

注意execute执行sql语句参数的两种情况:

  • execute("insert into t_sales(nickName, size) values('%s','%s');" % ("zack","L") )  #此时的%s为字符窜拼接占位符,需要引号加'%s'  (有sql注入风险)
  • execute("insert into t_sales(nickName, size) values(%s,%s);" , ("zack","L") ) #此时的%s为sql语句占位符,不需要引号%s
#***************************增删改查******************************************************
conn = pymysql.connect(host="localhost", user="root", passwd="", db='learningsql', charset='utf8', port=3306) #和mysql服务端设置格式一样(还可设置为gbk, gb2312)
#创建游标
cursor = conn.cursor()

insert_sql = "insert into t_sales(nickName,color,size,comment,saledate) values(%s,%s,%s,%s,%s);"
#返回受影响的行数
row1 = cursor.execute(insert_sql,("Bob", "黑色", "XL", "便宜实惠", "2019-04-20"))

update_sql = "update t_sales set color='白色' where id=%s;"
#返回受影响的行数
row2 = cursor.execute(update_sql,(1,))

select_sql = "select * from t_sales where id>%s;"
#返回受影响的行数
row3 = cursor.execute(select_sql,(1,))

delete_sql = "delete from t_sales where id=%s;"
#返回受影响的行数
row4 = cursor.execute(delete_sql,(4,))

#提交,不然无法保存新建或者修改的数据(增删改得提交)
conn.commit()
cursor.close()
conn.close()

批量插入和自增id

#***************************批量插入******************************************************
conn = pymysql.connect(host="localhost", user="root", passwd="", db='learningsql', charset='utf8', port=3306) #和mysql服务端设置格式一样(还可设置为gbk, gb2312)
#创建游标
cursor = conn.cursor()

insert_sql = "insert into t_sales(nickName,color,size,comment,saledate) values(%s,%s,%s,%s,%s);"
data = [("Bob", "黑色", "XL", "便宜实惠", "2019-04-20"),("Ted", "黄色", "M", "便宜实惠", "2019-04-20"),("Gary", "黑色", "M", "穿着舒服", "2019-04-20")]
row1 = cursor.executemany(insert_sql, data)

conn.commit()
#为插入的第一条数据的id,即插入的为5,6,7,new_id=5
new_id = cursor.lastrowid
print(new_id)
cursor.close()
conn.close()

获取查询数据

#***************************获取查找sql的查询数据******************************************************
conn = pymysql.connect(host="localhost", user="root", passwd="", db='learningsql', charset='utf8', port=3306) #和mysql服务端设置格式一样(还可设置为gbk, gb2312)
#创建游标
cursor = conn.cursor()

select_sql = "select id,nickname,size from t_sales where id>%s;"
cursor.execute(select_sql, (3,))

row1 = cursor.fetchone() #获取第一条数据,获取后游标会向下移动一行
row_n = cursor.fetchmany(3) #获取前n条数据,获取后游标会向下移动n行
row_all = cursor.fetchall() #获取所有数据,获取后游标会向下移动到末尾
print(row1)
print(row_n)
print(row_all)
#conn.commit()
cursor.close()
conn.close()

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

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

fetch获取数据类型

fetch获取的数据默认为元组格式,还可以获取字典类型的,如下:

#***************************获取字典格式数据******************************************************
conn = pymysql.connect(host="localhost", user="root", passwd="", db='learningsql', charset='utf8', port=3306) #和mysql服务端设置格式一样(还可设置为gbk, gb2312)
#创建游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

select_sql = "select id,nickname,size from t_sales where id>%s;"
cursor.execute(select_sql, (3,))

row1 = cursor.fetchall()

print(row1)

conn.commit()
cursor.close()
conn.close()

2.SQLAlchmy框架

SQLAlchemy的整体架构如下,建立在第三方的DB API上,将类和对象操作转换为数据库sql,然后利用DB API执sql语句得到结果。其适用于多种数据库。另外其内部实现了数据库连接池,方便进行多线程操作。

  • Engine,框架的引擎
  • Connection Pooling ,数据库连接池
  • ​​Dialect​​​,选择连接数据库的DB API种类,(pymysql,mysqldb等)``
  • Schema/Types,架构和类型
  • SQL Exprression Language,SQL表达式语言
  • ​​DB API​​:Python Database API Specification

2.1 执行原生sql

安装:pip install sqlalchemy

SQLAlchmy也可以不利用ORM,使用数据库连接池,类似pymysql模块执行原生sql。

#coding:utf-8

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

engine = create_engine(
"mysql+pymysql://root@127.0.0.1:3306/learningsql?charset=utf8",
max_overflow = 0, #超过连接池大小外最多创建的连接,为0表示超过5个连接后,其他连接请求会阻塞 (默认为10)
pool_size = 5, #连接池大小(默认为5)
pool_timeout = 30, #连接线程池中,没有连接时最多等待的时间,不设置无连接时直接报错 (默认为30)
pool_recycle = -1) #多久之后对线程池中的线程进行一次连接的回收(重置) (默认为-1)

# def task():
# conn= engine.raw_connection() #建立原生连接,和pymysql的连接一样
# cur = conn.cursor()
# cur.execute("select * from t_sales where id>%s",(2,))
# result = cur.fetchone()
# cur.close()
# conn.close()
# print(result)



# def task():
# conn = engine.contextual_connect() #建立上下文管理器连接,自动打开和关闭
# with conn:
# cur = conn.execute("select * from t_sales where id>%s",(2,))
# result = cur.fetchone()
# print(result)


def task():
cur =engine.execute("select * from t_sales where id>%s",(2,)) #engine直接执行
result = cur.fetchone()
cur.close()
print(result)

if __name__=="__main__":
for i in range(10):
t = threading.Thread(target=task)
t.start()

2.2 执行ORM语句

A. 创建和删除表

#coding:utf-8

import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, DateTime, Text

Base = declarative_base()

class User(Base):
__tablename__="users"
id = Column(Integer,primary_key=True)
name = Column(String(32),index=True, nullable=False) #创建索引,不为空
email = Column(String(32),unique=True)
ctime = Column(DateTime, default = datetime.datetime.now) #传入方法名datetime.datetime.now
extra = Column(Text,nullable=True)

__table_args__ = {

# UniqueConstraint('id', 'name', name='uix_id_name'), #设置联合唯一约束
# Index('ix_id_name', 'name', 'email'), # 创建索引
}

def create_tbs():
engine = create_engine("mysql+pymysql://root@127.0.0.1:3306/learningsql?charset=utf8",max_overflow=2,pool_size=5)
Base.metadata.create_all(engine) #创建所有定义的表

def drop_dbs():
engine = create_engine("mysql+pymysql://root@127.0.0.1:3306/learningsql?charset=utf8",max_overflow=2,pool_size=5)
Base.metadata.drop_all(engine) #删除所有创建的表

if __name__=="__main__":
create_tbs() #创建表
#drop_dbs() #删除表

B.表中定义外键关系(一对多,多对多)

思考:下面代码中的一对多关系,relationship 定义在了 customer 表中,应该定义在 PurchaseOrder 更合理?

注意:mysql 数据库中避免使用 order做为表的名字,order 为一个 mysql 关键字,做为表名字时必须用反引号order (键盘数字1旁边的符号)。

#coding:utf-8

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,Text,DateTime,ForeignKey,Float
from sqlalchemy.orm import relationship
import datetime

engine = create_engine("mysql+pymysql://root@127.0.0.1:3306/learningsql?charset=utf8") #数据库有密码时,//root:12345678@127.0.0.1:3306/
Base = declarative_base()

class Customer(Base):
__tablename__="customer" #数据库中保存的表名字

id = Column(Integer,primary_key=True)
name = Column(String(64),index=True,nullable=False)
phone = Column(String(16),nullable=False)
address = Column(String(256),nullable=False)
purchase_order_id = Column(Integer,ForeignKey("purchase_order.id")) #关键关系,关联表的__tablename__="purchase_order"

# 和建立表结构无关,方便外键关系查询,backref反向查询时使用order_obj.customer
purchase_order = relationship("PurchaseOrder",backref="customer")



class PurchaseOrder(Base):
__tablename__ = "purchase_order" #mysql数据库中表的名字避免使用order,order为一个关键字,使用时必须用反引号`order` (键盘数字1旁边的符号)
id=Column(Integer,primary_key=True)
cost = Column(Float,nullable=True)
ctime = Column(DateTime,default =datetime.datetime.now)
desc = Column(String(528))

#多对多关系时,secondary为中间表
product = relationship("Product",secondary="order_to_product",backref="purchase_order")

class Product(Base):
__tablename__ = "product"
id = Column(Integer,primary_key=True)
name = Column(String(256))
price = Column(Float,nullable=False)

class OrdertoProduct(Base):
__tablename__ = "order_to_product"
id = Column(Integer,primary_key=True)
product_id = Column(Integer,ForeignKey("product.id"))
purchase_order_id = Column(Integer,ForeignKey("purchase_order.id"))



if __name__ == "__main__":
Base.metadata.create_all(engine)
#Base.metadata.drop_all(engine)

C.增删改查操作

增删改查

#coding:utf-8

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,Text,DateTime,ForeignKey,Float
from sqlalchemy.orm import relationship,sessionmaker
from sqlalchemy.sql import text
import datetime

engine = create_engine("mysql+pymysql://root@127.0.0.1:3306/learningsql?charset=utf8") #数据库有密码时,//root:12345678@127.0.0.1:3306/, 设置utf8防止中文乱码
Base = declarative_base()

class Customer(Python操作MySQL数据库的三个模块
转载来源:http://www.mswzjz.cn/qtweb/news24/253924.html

攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能