数据库中的数据表可以看做是现实世界中一类事物的抽象,而表中的每一行数据都可以看做是一个实例「即现实世界的实体」。在现实世界中每个事物/实体都不是单独不是单独存在的,都与其他事物或实体存在或多或少的关联,对应在数据库中,数据表之间也存在着不同的关联,我们将这种关联称之为关系。
关系:提供从一张表到另一张表的数据访问。关系可以将一个表中的一条记录与另一个表中的一条记录、一条记录与多条其他记录或一个表中的所有记录与另一个表中的所有记录联在一起,这根据您在关系图中创建关系时指定的条件决定。
关系数据库中表与表之间一般存在三种关系:一对一、一对多、多对多。
关系数据库包含一个或多个相关表,这些表一起使用时会包含您需要的信息。一次只在一个表中存储数据的每个实例,但可以访问和显示任何相关表的这些数据。您可以更改相关数据的任何实例,这些更改会动态出现在所有位置。这意味着在一个位置更改数据时,无论该数据出现在哪里都会更改,使您始终获得最新数据。利用关系数据库可以使用最新状态的数据,高效、灵活地建立和管理数据,同时节省磁盘空间。
要从相关表中检索数据并将其拷贝到当前表,需要定义查找。拷贝的数据现在存储在两个位置,就如同将其拷贝并粘贴到目标字段。查找的数据在拷贝时处于最新状态,但在拷贝后,它处于静态,除非重新查找。
一对多关系
在一个表中有一条记录,在另外一个表中有多条记录与之相匹配。一对多典型的示例即客户和订单的关系,一个客户可以创建多个订单,而一个订单只能对应一个客户。
在 SQLAlchemy 中订单表通过外键(foreign key)来引用客户表,客户表通过 relationship() 方法来关联订单表。
典型使用示例如下
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
order = relationship('Order', backref='users')
class Order(Base):
__tablename__ = 'order'
id = Column(Integer, primary_key=True)
number = Column(Integer)
user_id = Column(Integer, ForeignKey('users.id'))
向数据库中插入数据:
user1 = User('kein')
user2 = User('ye')
order1 = Order(1)
order2 = Order(2)
order1.users = user1
order2.users = user1
session.add(user1)
session.commit()
查询数据库中的数据
# 依据用户查询订单
order = session.query(User).filter(User.name == 'kein').first().order
# 依据订单查询用户
user = session.query(Order).filter(Order.number == 1).first().users
一对一关系
在一个表中有一条记录,则在另一张表中有一条记录相匹配。一般是看主表每一个字段对应另一张表的匹配记录条数。一对一本质上是两个表之间的双向关系,要做到这一点只需要在一对多关系的基础上设置 relationship 方法的 uselist 参数为 false 即可。由于一对一关系与一对多关系基本相同,这里不再做过多的描述,各位看官可以参照一对多关系来完成相关内容。
多对多关系
一个表中的多个记录与另一个表中的多个记录相关联时即产生多对多关系。而我们常用的关系数据库往往不支持直接在两个表之间进行多对多的联接,为了解决这个问题,就需要引入第三个表,将多对多关系拆分为两个一对多的关系,我们称这个表为联接表。大学中选修课和学生之间的关系就是一个典型的多对多关系,一个学生可以选修多个选修课,一个选修课有多个学生学习。
使用 SQLAlchemy 来创建多对多关系数据表:
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
association_table = Table('association',Base.metadata,
Column('course_id', Integer, ForeignKey('course.id')),
Column('student_id', Integer, ForeignKey('student.id'))
)
class Course(Base):
__tablename__ = 'course'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
student = relationship("Student", secondary=association_table, backref='course')
def __repr__(self):
return "name:%r" %self.name
class Student(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
def __repr__(self):
return "name:%r" %self.name
向数据库中添加数据
s1 = Student(name = 's1')
s2 = Student(name = 's2')
c1 = Course(name = 'c1')
c2 = Course(name = 'c2')
c1.student = [s1, s2]
c2.student = [s1, s2]
session.add(c1)
session.add(c2)
session.commit()
查询数据库中的数据
s1_course = session.query(Student).filter(Student.name == 's1').first().course
print(s1_course)
c1_student = session.query(Course).filter(Course.id == 1).first().student
print(c1_student)