python使用mysql的两种使用方式


当前第2页 返回上一页

然后向两个表中插入数据:

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分组后,如何统计记录条数

mysql 没有varchar(max) 类型

一次mysql死锁排查过程的全纪录

mysql如何查看用户权限

mysql使用变量实现各种排序实例详解

详解mysql通讯协议

详解mysql 4g内存服务器配置优化

mysql能干什么

详解高性能mysql主从架构的复制原理及配置

mysql 中,如何计算一组数据的中位数

更多相关阅读请进入《mysql》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

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



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...