Part11 – MySQL和ORM之sqlalchemy

时间:2022-06-27 15:03:28

本节内容

1.MySQL
1.MySQL基础
2.Python连接MySQL
2.ORM之sqlalchemy

一、MySQL

MySQL是最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的RDBMS(Relational Database Management System,即关系数据库管理系统)应用软件之一。由瑞典MySQL AB公司开发,目前属于Oracle公司。MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
  • Mysql支持大型的数据库。可以处理拥有上千万条记录的大型数据库。
  • MySQL使用标准的SQL数据语言形式。
  • Mysql可以允许于多个系统上,并且支持多种语言。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。
  • Mysql对PHP有很好的支持,PHP是目前最流行的Web开发语言。
  • MySQL支持大型数据库,支持5000万条记录的数据仓库,32位系统表文件最大可支持4GB,64位系统支持最大的表文件为8TB。
  • Mysql是可以定制的,采用了GPL协议,你可以修改源码来开发自己的Mysql系统。

1、MySQL基础

1.MySQL操作

MySQL、ORM:http://www.cnblogs.com/alex3714/articles/5950372.html
MySQL练习题:http://www.cnblogs.com/wupeiqi/articles/5729934.html
MySQL更多:http://www.cnblogs.com/wupeiqi/articles/5713323.html

2.MySQL数据类型

MySQL中定义数据字段的类型对你数据库的优化是非常重要的。
MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
  • 数值类型
MySQL支持所有标准SQL数值数据类型。这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。

Part11 – MySQL和ORM之sqlalchemy

  • 日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。TIMESTAMP类型有专有的自动更新特性,将在后面描述。

Part11 – MySQL和ORM之sqlalchemy

  • 字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

Part11 – MySQL和ORM之sqlalchemy

CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
BINARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。TEXT有4种类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT,分别对应4种BLOB类型,有相同的最大长度和存储需求。

2、Python连接MySQL

pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同。
Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
import pymysql  
    
# 创建连接  
conn = pymysql.connect(host='192.168.3.121', port=3306, user='root', passwd='123456', db='oldboydb')  
# 创建游标  
cursor = conn.cursor()  
    
# 执行SQL,并返回收影响行数  
effect_row = cursor.execute("select * from student")  
print(cursor.fetchone())  
print(cursor.fetchone())  
print(cursor.fetchall())  
    
# 提交,不然无法保存新建或者修改的数据  
# conn.commit()  
    
# 关闭游标  
cursor.close()  
# 关闭连接  
conn.close()  
pymysql基本使用
其他具体操作参考:
mysqldb: http://www.cnblogs.com/wupeiqi/articles/5095821.html
pymysql、SQLAlchemy: http://www.cnblogs.com/wupeiqi/articles/5713330.html

二、ORM之sqlalchemy

ORM英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。
更详细ORM介绍:http://www.cnblogs.com/alex3714/articles/5978329.html

1、基础知识

Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
engine = create_engine("mysql+pymysql://root:123456@192.168.3.121/oldboydb?charset=utf8",
                encoding='utf-8', echo=False)  
#写入中文时候要加 ?charset=utf8 ,echo=False 不显示sql执行过程  
    
常用SQLALCHEMY列数据类型   
类型名称        Python数据类型      描述  
Integer         int                 常规整形,通常为32位  
SmallInteger    int                 短整形,通常为16位  
BigInteger      int或long            精度不受限整形  
Float           float               浮点数  
Numeric         decimal.Decimal     定点数  
String          str                 可变长度字符串  
Text            str                 可变长度字符串,适合大量文本  
Unicode         unicode             可变长度Unicode字符串  
Boolean         bool                布尔型  
Date            datetime.date       日期类型  
Time            datetime.time       时间类型  
Interval        datetime.timedelta  时间间隔  
Enum            str                 字符列表  
PickleType      任意Python对象      自动Pickle序列化  
LargeBinary     str                 二进制  
    
常见SQLALCHEMY列配置参数  
可选参数        描述  
primary_key     如果此参数为True,该列为列表的主键,该列不允许有空值(null)  
                注意:数据库中查询结果显示空白是0长度字符串,不是空值(null)  
unique          唯一属性,如果此参数为True,该列不允许有相同值,但允许有一个空值  
index           索引,如果参数为True,为该列创建索引,查询效率会更高,但会增加修改表的时间  
nullable        如果此参数为True,该列允许为空。如果参数为False,该列不允许空值  
default         定义该列的默认值     
View Code

Part11 – MySQL和ORM之sqlalchemy

2、增删改查

Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey  
from sqlalchemy.orm import mapper  
    
#对于不用程序经常维护的表,可以通过如下方式创建  
metadata = MetaData()  
    
user = Table('user', metadata,  
             Column('id', Integer, primary_key=True),  
             Column('name', String(50)),  
             Column('fullname', String(50)),  
             Column('password', String(12))  
             )  
    
class User(object):  
    def __init__(self, name, fullname, password):  
        self.name = name  
        self.fullname = fullname  
        self.password = password  
    
mapper(User,user)    
# the table metadata is created separately with the Table construct,   
# then associated with the User class via the mapper() function  
对于不用程序经常维护的表,可以通过如下方式创建
Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
from sqlalchemy import create_engine  
from sqlalchemy.ext.declarative import declarative_base  
from sqlalchemy import Column, Integer, String, DATE,Enum  
from sqlalchemy.orm import sessionmaker  
    
engine = create_engine("mysql+pymysql://root:123456@192.168.3.121/oldboydb",  
                       encoding='utf-8', echo=False) #echo=True,即打印过程  
    
Base = declarative_base()  # 生成orm基类  
    
class User(Base):  
    __tablename__ = 'user'  # 表名  
    id = Column(Integer, primary_key=True)  
    name = Column(String(32))  
    password = Column(String(64))  
    
    def __repr__(self):  
        '''''使查询结果中显示具体信息,不是内存地址'''  
        return "<%s name:%s>"%(self.id,self.name)  
    
class Student(Base):  
    __tablename__ = "student"  
    id = Column(Integer,primary_key=True)  
    name = Column(String,nullable=False)  
    register_date = Column(DATE,nullable=False)  
    gender = Column(Enum('M','F'),nullable=False)  
    
    def __repr__(self):  
        '''''使查询结果中显示具体信息,不是内存地址'''  
        return "<%s name:%s>" % (self.id, self.name)  
    
    
###########创建表结构  
# Base.metadata.create_all(engine)  
    
    
###########创建数据  
Session_class = sessionmaker(bind=engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例  
Session = Session_class()  # 生成session实例  
# user_obj = User(name="alex", password="alex3714")  # 生成你要创建的数据对象  
# print(user_obj.name, user_obj.id)  # 此时还没创建对象呢,不信你打印一下id发现还是None  
# Session.add(user_obj)  # 把要创建的数据对象添加到这个session里, 一会统一创建  
# print(user_obj.name, user_obj.id)  # 此时也依然还没创建  
# Session.commit()  # 现此才统一提交,创建数据  
    
 
# ###########删除  
# data = Session.query(User).filter_by(name="alex").first()  
# Session.delete(data)  
# Session.commit()  
    
###########单个修改  
# my_user = Session.query(User).filter_by(name="alex").first()  
# my_user.name = "Alex Li"  
# Session.commit()  
    
    
###########查询数据  
#单个查询条件  
# data = Session.query(User).filter_by(name="alex").all()     #把所有符合条件的数据取成一个列表  
# data = Session.query(User).filter_by(name="alex").first()     #取出符合条件的第一个  
# data = Session.query(User).filter_by(id = 1).all()  
# data = Session.query(User).filter(User.id == 2).all()  
    
#多个查询条件组合查询  
# data = Session.query(User).filter(User.id > 1).filter(User.name == 'alex').all()  
    
#获取所有数据  
# print(Session.query(User.name,User.id).all() )  
    
#统计  
# data = Session.query(User).filter(User.name.like("Ra%")).count()  
    
#分组  
# from sqlalchemy import func  
# data = Session.query(func.count(User.name),User.name).group_by(User.name).all()  
    
#联表(join)  
# data = Session.query(User, Student).filter(User.id == Student.id).all()  
# data = Session.query(User).join(Student).all()  #如果两个表已经有了外键关联关系  
# data = Session.query(User).join(Student, isouter=True).all()  
    
#print(data)  
# print(data.id,data.name,data.password)  
    
    
###########数据会滚  
# my_user = Session.query(User).filter_by(id=1).first()  
# my_user.name = "Jack"  
# fake_user = User(name='Rain', password='12345')  
# Session.add(fake_user)  
# print(Session.query(User).filter(User.name.in_(['Jack', 'rain'])).all())  # 这时看session里有你刚添加和修改的数据(脏数据)  
# Session.rollback()  # 此时你rollback一下  
# print(Session.query(User).filter(User.name.in_(['Jack', 'rain'])).all())  # 再查就发现刚才添加的数据没有了。  
使用sqlalchemy实现表创建,以及数据增删改查

3、外键关联

Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
from sqlalchemy import create_engine  
from sqlalchemy.ext.declarative import declarative_base  
from sqlalchemy import Column, Integer, String, DATE,Enum,ForeignKey  
from sqlalchemy.orm import sessionmaker,relationship  
    
engine = create_engine("mysql+pymysql://root:123456@192.168.3.121/oldboydb",  
                       encoding='utf-8', echo=False) #echo=True,即打印过程  
    
Base = declarative_base()  # 生成orm基类  
    
class Student(Base):  
    __tablename__ = "student"  
    id = Column(Integer, primary_key=True)  
    name = Column(String(32), nullable=False)  
    register_date = Column(DATE, nullable=False)  
    
    def __repr__(self):  
        '''''使查询结果中显示具体信息,不是内存地址'''  
        return "<%s name:%s>" % (self.id, self.name)  
    
class StudyRecord(Base):  
    __tablename__ = 'study_record'  # 表名  
    id = Column(Integer, primary_key=True)  
    day = Column(Integer,nullable=False)  
    status = Column(String(32), nullable=False)  
    stu_id = Column(Integer,ForeignKey('student.id'))  
    
    student = relationship("Student", backref="my_study_record")  # 这个nb,允许你在student表里通过backref字段反向查出所有它在study_record表里的关联项,建立在内存中  
    
    def __repr__(self):  
        '''''使查询结果中显示具体信息,不是内存地址'''  
        return "<%s day:%s status:%s>"%(self.student.name,self.day,self.status)  
    
###########创建表结构(外键)  
#Base.metadata.create_all(engine)  
    
    
###########创建数据  
Session_class = sessionmaker(bind=engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例  
session = Session_class()  # 生成session实例  
    
# s1 = Student(name="Alex",register_date='2017-01-23')  
# s2 = Student(name="Jack",register_date='2017-02-23')  
# s3 = Student(name="Rain",register_date='2017-03-23')  
# s4 = Student(name="Eric",register_date='2017-04-23')  
#  
# study_obj1 = StudyRecord(day=1,status="YES",stu_id=1)  
# study_obj2 = StudyRecord(day=2,status="NO",stu_id=1)  
# study_obj3 = StudyRecord(day=3,status="YES",stu_id=1)  
# study_obj4 = StudyRecord(day=1,status="YES",stu_id=2)  
#  
# #session.add_all([s1,s2,s3,s4,study_obj1,study_obj2,study_obj3,study_obj4])  
# session.add_all([s1,s2,s3,s4])  
# session.add_all([study_obj1,study_obj2,study_obj3,study_obj4])  
# session.commit()  
    
    
###########查询  
# stu_obj = session.query(Student,StudyRecord).filter(Student.name=='alex')\  
#     .filter(Student.id==StudyRecord.stu_id).all()     #返回的是列表  
stu_obj = session.query(Student).filter(Student.name=='alex').first()  
    
print(stu_obj.my_study_record)  
View Code

4、多外键关联

Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
from sqlalchemy import Integer, ForeignKey, String, Column  
from sqlalchemy.ext.declarative import declarative_base  
from sqlalchemy.orm import relationship  
from sqlalchemy import create_engine  
    
engine = create_engine("mysql+pymysql://root:123456@192.168.3.121/oldboydb",  
                       encoding='utf-8', echo=False) #echo=True,即打印过程  
    
Base = declarative_base()  # 生成orm基类  
    
class Customer(Base):  
    __tablename__ = 'customer'  
    id = Column(Integer, primary_key=True)  
    name = Column(String(64))  
    
    billing_address_id = Column(Integer, ForeignKey("address.id"))  
    shipping_address_id = Column(Integer, ForeignKey("address.id"))  
    
    # foreign_keys=[billing_address_id]如果不写添加数据时程序会分不清两个relationship  
    billing_address = relationship("Address", foreign_keys=[billing_address_id])  
    shipping_address = relationship("Address", foreign_keys=[shipping_address_id])  
    
class Address(Base):  
    __tablename__ = 'address'  
    id = Column(Integer, primary_key=True)  
    street = Column(String(64))  
    city = Column(String(64))  
    state = Column(String(64))  
    
    def __repr__(self):  
        return self.street  
    
if __name__ == '__main__':  
    ###########创建表结构(多外键)  
    Base.metadata.create_all(engine) 
创建表结构(orm_many_fk)
Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
from orm_many_fk import Customer,Address,engine  
from sqlalchemy.orm import sessionmaker  
    
###########创建数据  
Session_class = sessionmaker(bind=engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例  
session = Session_class()  # 生成session实例  
    
# addr1 = Address(street="Tiantongyuan",city="ChangPing",state="Beijing")  
# addr2 = Address(street="Wudaokou",city="Haidian",state="Beijing")  
# addr3 = Address(street="Yanjiao",city="LangFang",state="Hebei")  
# session.add_all([addr1,addr2,addr3])  
#  
# c1 = Customer(name="Alex",billing_address=addr1,shipping_address=addr2)  
# c2 = Customer(name="Jack",billing_address=addr3,shipping_address=addr3)  
# session.add_all([c1,c2])  
#  
# session.commit()  
    
    
###########查询  
obj = session.query(Customer).filter(Customer.name=="alex").first()  
print(obj.name,obj.billing_address,obj.shipping_address)  
创建、查询数据

5、多对多关系

Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
#一本书可以有多个作者,一个作者又可以出版多本书  
from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey  
from sqlalchemy.orm import relationship  
from sqlalchemy.ext.declarative import declarative_base  
from sqlalchemy import create_engine  
    
engine = create_engine("mysql+pymysql://root:123456@192.168.3.121/oldboydb?charset=utf8",   #?charset=utf8支持中文  
                       encoding='utf-8', echo=False) #echo=True,即打印过程  
    
Base = declarative_base()  
    
book_m2m_author = Table('book_m2m_author', Base.metadata,  
                        Column('book_id',Integer,ForeignKey('books.id')),  
                        Column('author_id',Integer,ForeignKey('authors.id')),  
                        )  
    
class Book(Base):  
    __tablename__ = 'books'  
    id = Column(Integer,primary_key=True)  
    name = Column(String(64))  
    pub_date = Column(DATE)  
    authors = relationship('Author',secondary=book_m2m_author,backref='books')  
    # secondary=book_m2m_author,与Author做关联,查询"authors"时去book_m2m_author中查  
    # backref='books',通过Author反向查询Book时,使用"author表查询实例.books"  
    
    def __repr__(self):  
        return self.name  
    
class Author(Base):  
    __tablename__ = 'authors'  
    id = Column(Integer, primary_key=True)  
    name = Column(String(32))  
    
    def __repr__(self):  
        return self.name  
    
if __name__ == '__main__':  
    ###########创建表结构(多对多)  
    Base.metadata.create_all(engine)  
创建表结构(orm_m2m)
Part11 – MySQL和ORM之sqlalchemyPart11 – MySQL和ORM之sqlalchemy
import orm_m2m  
from sqlalchemy.orm import sessionmaker  
    
###########创建数据  
Session_class = sessionmaker(bind=orm_m2m.engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例  
session = Session_class()  # 生成session实例  
    
# b1 = orm_m2m.Book(name="learn python with Alex",pub_date="2014-05-22")  
# b2 = orm_m2m.Book(name="learn Zhuangbility with Alex",pub_date="2014-05-22")  
# b3 = orm_m2m.Book(name="learn hook up girls with Alex",pub_date="2014-05-22")  
b4 = orm_m2m.Book(name="跟Alex去泰国",pub_date="2014-05-22")  
#  
# a1 = orm_m2m.Author(name="Alex")  
# a2 = orm_m2m.Author(name="Jack")  
# a3 = orm_m2m.Author(name="Rain")  
#  
# 建立第三张表的关联关系  
# b1.authors = [a1,a3]  
# b3.authors = [a1,a2,a3]  
#  
# session.add_all([b1,b2,b3,a1,a2,a3])  
session.add(b4)  
session.commit()  
    
    
###########查询  
# author_obj = session.query(orm_m2m.Author).filter(orm_m2m.Author.name=="alex").first()  
# print(author_obj.books)  
# print(author_obj.books[1].pub_date)  
# book_obj = session.query(orm_m2m.Book).filter(orm_m2m.Book.id==2).first()  
# print(book_obj.authors)  
    
    
###########删除,删除数据时不用管boo_m2m_authors,sqlalchemy会自动帮你把对应的数据删除  
#通过书删除作者  
# author_obj = session.query(orm_m2m.Author).filter_by(name="Jack").first()  
# book_obj = session.query(orm_m2m.Book).filter_by(name="跟Alex学把妹").first()  
# book_obj.authors.remove(author_obj)  # 从一本书里删除一个作者  
    
#直接删除作者。删除作者时,会把这个作者跟所有书的关联关系数据也自动删除  
# author_obj =session.query(orm_m2m.Author).filter_by(name="Alex").first()  
# session.delete(author_obj)  
#  
# session.commit()  
创建、查询数据

参考:

http://www.cnblogs.com/alex3714/articles/5248247.html