然后向两个表中插入数据:
Base.metadata.create_all(engine)#创建表结构 Session_class = sessionmaker(bind=engine) session = Session_class() s1 = Student(name = "xiaoming",register_date="2015-06-07") s2 = Student(name = "huahua",register_date="2015-06-08") s3 = Student(name = "caicai",register_date="2015-06-09") s4 = Student(name = "zhazha",register_date="2015-06-04") 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]) session.add_all([study_obj1,study_obj2,study_obj3,study_obj4]) session.commit()
批量插入用add_all,里面用一个列表放入要插入的数据, 注意的是,因为建立了外键,所以在添加数据的时候,study_record的数据一定要在student表数据插入之后才能够被插入,如果一起插入就会报错
现在我们要查询xiaoming一共上了几节课,那应该怎么做呢:
import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,DATE,ForeignKey from sqlalchemy.orm import sessionmaker,relationship engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb",encoding='utf-8') 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") 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 = Session_class() stu_obj = session.query(Student).filter(Student.name=='xiaoming').first() print(stu_obj.my_study_record) session.commit()
注意上面代码标红的这个语句,我们引入了relationship,然后这个允许你在study_record表里通过backref字段反向查出所有它在student表里的关联项,实现了一个双向查找,即关联student表,在studyrecord中通过student字段就可以查 student表中的所有字段,反过来,我们可以在student表中通过 my_study_record字段反查studyrecord里面的数据,然后代表着我们在下面查到的xiaoming,可以.my_study_record就可以查询出在studyrecord表中还有xiaoming的id的数据项
多外键关联
首先我们创建两个表customer和address两个表,其中customer表中有address的两个外键:
import 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:root@192.168.123.207/xumingdb",encoding='utf-8') Base = declarative_base() 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")) billing_address = relationship("Address") shipping_address = relationship("Address") 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 Base.metadata.create_all(engine) # 创建表结构
然后我们向两个表中插入数据:
from day12 import sqlalchemy_multi_fk from sqlalchemy.orm import sessionmaker Session_class = sessionmaker(bind=sqlalchemy_multi_fk.engine) session = Session_class() addr1 = sqlalchemy_multi_fk.Address(street="XiZangBeiLu",city="ShangHai",state="ShangHai") addr2 = sqlalchemy_multi_fk.Address(street="YuHu",city="XiangTan",state="HuNan") addr3 = sqlalchemy_multi_fk.Address(street="ZhongXinZhen",city="SuQian",state="JiangSu") session.add_all([addr1,addr2,addr3]) c1 = sqlalchemy_multi_fk.Customer(name="xiaoming",billing_address=addr1,shipping_address=addr2) c2 = sqlalchemy_multi_fk.Customer(name="jack",billing_address=addr3,shipping_address=addr3) session.add_all([c1,c2]) session.commit()
这样插入会出现一个错误:
sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Customer.billing_address - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.
说白了就是我们现在在做关联查询的时候,有两个字段同时关联到了Address表中 ,在做反向查询的时候它分不清楚谁是谁,通过address反向查的时候分不清哪个字段代表billing_address,哪个字段是代表了shipping_address.那我们怎么解决呢?
billing_address = relationship("Address",foreign_keys=[billing_address_id]) shipping_address = relationship("Address",foreign_keys=[shipping_address_id])
在创建反向查询的语句中添加foreign_keys
参数就可以了
添加数据成功!!
这个时候我们要查询customer的地址:
obj = session.query(sqlalchemy_multi_fk.Customer).filter(sqlalchemy_multi_fk.Customer.name=="xiaoming").first() print(obj.name,obj.billing_address,obj.shipping_address)
多对多关系
现在让我们设计一个能描述“图书”与“作者”的关系的表结构,需求是:
1.一本书可以有好几个作者一起出版
2.一个作者可以写好几本书
首先我们看一下一般的思路 :
两个表,然后我们在遇到一本书有多个作者共同参与出版,就把作者id写在一起,但是这样不利于查询
那我们可以再添加一张表:
这就实现了双向的一对多,一个作者可以包含多本书,一本书可以包含多个作者。这就形成了多对多。
来看代码的实现:
首先还是先建立数据表:
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:root@192.168.123.207/xumingdb",encoding='utf-8') Base = declarative_base() 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') 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 Base.metadata.create_all(engine) # 创建表结构
这里我们使用了另外一种建立表的方式,建立了第三张表book_m2m_auther,这张表建立起来后基本上不需要我们去人为的添加数据,对用户来讲是不用关心这里面有什么数据,是由orm自动帮你维护的。也就不需要给它建立映射关系了。
但是在mysql端其实已经关联上了,因为外键已经建立好了,在orm查询的时候,还要做一个orm级别的 内存对象的映射:relationship,告诉book表和author表在查询数据的时候去哪张表里查询。
所以看上面的红色的代码,通过secondary这个字段去查第三张表。
这个时候就建立好了多对多的关系。我们就可以插入数据看效果:(先把表建立起来再说)
from day12 import sqlalchemy_multitomulti from sqlalchemy.orm import sessionmaker Session_class=sessionmaker(bind=sqlalchemy_multitomulti.engine) session = Session_class() b1 = sqlalchemy_multitomulti.Book(name="book1",pub_date="2014-05-16") b2 = sqlalchemy_multitomulti.Book(name="book2",pub_date="2012-03-16") b3 = sqlalchemy_multitomulti.Book(name="book3",pub_date="2016-06-16") a1 = sqlalchemy_multitomulti.Author(name="xiaoming") a2 = sqlalchemy_multitomulti.Author(name="jack") a3 = sqlalchemy_multitomulti.Author(name="Rain") b1.authors = [a1,a3] b2.authors = [a2,a3] b3.authors = [a1,a2,a3] session.add_all([b1,b2,b3,a1,a2,a3]) session.commit()
上面红色标记是建立关联关系,这样建立出来之后,book_m2m_author表自动就会有数据。
当然如果我们想要插入中文的书。即插入的数据有中文,我们要怎么做呢:
engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb?charset=utf8",encoding='utf-8') Base = declarative_base()
需要在创建数据库连接的时候在数据库后面加上 ?charset=utf8
现在数据插入之后,最终要实现查询数据:
1.查看作者xiaoming出版了多少本书:
author_obj = session.query(sqlalchemy_multitomulti.Author).filter(sqlalchemy_multitomulti.Author.name=="xiaoming").first() print(author_obj.books)
2.查看书b2是哪些作者出版的 :
book_obj = session.query(sqlalchemy_multitomulti.Book).filter(sqlalchemy_multitomulti.Book.id==2).first() print(book_obj.authors)
多对多删除:
在删除数据的时候我们也同样的不需要管book_m2m_author表,sqlalchemy会自动帮我们把对应的数据删除:
通过书删除作者:
author_obj = session.query(sqlalchemy_multitomulti.Author).filter(sqlalchemy_multitomulti.Author.name=="xiaoming").first() book_obj = session.query(sqlalchemy_multitomulti.Book).filter(sqlalchemy_multitomulti.Book.id==2).first() book_obj.authors.remove(author_obj) session.commit()
这个时候图书2的关联关系会自动少一个
直接删除作者:
author_obj = session.query(sqlalchemy_multitomulti.Author).filter(sqlalchemy_multitomulti.Author.name=="xiaoming").first() session.delete(author_obj) session.commit()
总结
以上所述是小编给大家介绍的python使用mysql的两种使用方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
更多相关Mysql内容来自木庄网络博客
标签:Mysql
相关阅读 >>
更多相关阅读请进入《mysql》频道 >>

数据库系统概念 第6版
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。