sqlalchemy外键和relationship查询

原文地址:https://www.cnblogs.com/goldsunshine/p/9269880.html

阅读目录

前面的文章中讲解了外键的基础知识和操作,上一篇文章讲解了sqlalchemy的基本操作。前面两篇文章都是作为铺垫,为下面的文章打好基础。记得初一时第一次期中考试时考的不好,老爸安慰我说:“学习是一个循序渐进的过程”,而我的就是按照这样思路来学习数据库外键。首先是了解外键基础理论,然后是sqlalchemy基本操作,最后才到sqlalchemy操作外键。

回到顶部

一、sqlalchemy体现的外键特性

1.外键回顾

外键的出现是因为两张表之间需要有关联,为了保证数据的完整性和唯一性而产生的。有外键时会有两张以上的表,分为主表和附表。附表中数据往往是主表中数据的延伸,附表中有外键关联到主表的主键上。

在sqlalchemy的ORM模型中,定义表时指定主键和外键。

主键定义:在字段信息后面加上primary_key=True

name = Column(String(20),primary_key=True)

外键定义:在字段后面加上Foreignkey(主表.主键)

company_name = Column(String(32),ForeignKey("company.name"))
company = relationship("Company",backref="phone_of_company") 

另外在定义主键时往往还会定义一个relationship,什么作用呢?下文见分晓。

2.定义表

定义两张表,company和phone,company中的name是主键,phone中的id是主键,并且phone中定义company_name外键。

sql_foreign_models.py

 1 #coding:utf-8
 2
 3 from sqlalchemy import create_engine
 4 from sqlalchemy.ext.declarative import declarative_base
 5 from sqlalchemy import Column,Integer,String,DATE,ForeignKey  #导入外键
 6 from sqlalchemy.orm import  relationship  #创建关系
 7
 8 engine = create_engine("mysql+mysqldb://root:[email protected]:3306/test",
 9                        encoding="utf-8")
10
11 Base = declarative_base() #生成orm基类
12
13 class Company(Base):
14
15     __tablename__ = "company"
16
17     name = Column(String(20),primary_key=True)
18     location = Column(String(20))
19
20     def __repr__(self):
21         return "name:{0} location:{1}".format(self.name,self.location)
22
23 class Phone(Base):
24
25     __tablename__ = "phone"
26
27     id = Column(Integer,primary_key=True)
28     model = Column(String(32))
29     price = Column(String(32))
30     company_name = Column(String(32),ForeignKey("company.name"))
31     company = relationship("Company",backref="phone_of_company")
32
33     def __repr__(self):
34         return "{0} model:{1},sales:{2} sales:{3} price:{4}".format(self.id,self.model,self.sales,self.price)
35
36 Base.metadata.create_all(engine) #创建表

3.创建表

python sql_foreign_models.py

4.插入数据

sql_foreign_insert.py

 1 #coding:utf-8
 2
 3 from sql_foreign_models import *
 4 from sql_insert import *
 5
 6 companys = {
 7            "Apple":"Amercian",
 8            "Xiaomi":"China",
 9            "Huawei":"China",
10            "Sungsum":"Korea",
11            "Nokia":"Finland"
12            }
13
14 phones = (
15         [1,"iphoneX","Apple",8400],
16         [2,"xiaomi2s","Xiaomi",3299],
17         [3,"Huaweimate10","Huawei",3399],
18         [4,"SungsumS8","SungSum",4099],
19         [5,"NokiaLumia","Nokia",2399],
20         [6,"iphone4s","Apple",3800]
21         )
22
23
24 for key in companys:
25
26     new_company = Company(name=key,location=companys[key])
27     insert(new_company)
28
29 for phone in phones:
30     id = phone[0]
31     model = phone[1]
32     company_name = phone[2]
33     price = phone[3]
34
35     new_phone = Phone(id=id,model=model,company_name=company_name,price=price)
36     insert(new_phone)

写入数据库

python sql_foreign_insert.py

5.sqlalchemy外键操作

总结外键的优点有两个:保证数据的完整性和保证数据的一致性。那么在sqlqlchemy如何体现完整性和一致性呢?通过数据的插入和删除来体现。

完整性:附表插入数据时会检查外键所在字段在主表中是否存在

在phone表中插入数据:(7,Blackberry,“RIM”,3200)黑莓手机,所在公司是RIM。

new_phone = Phone(id=7,model="BlackBerry",company_name="RIM",price=3200)
insert(new_phone)

报错:不能添加或者更新一个子行,有一个外键关联。

因为主表company的主键,也就是phone外键关联的字段没有“RIM”,所以当phone写入数据时会检查company_name字段的值是否在company中存在。而company中不存在该值,所以不能写入。这样做就保证了数据的完整性。

一致性:一致性的规则有多个,具体如下引用:


1

2

3

4

5

6

7

8

外键约束对父表的含义:

   在父表上进行update/delete以更新或删除在子表中有一条或多条对应匹配行的候选键时,父表的行为取决于:在定义子表的外键时指定的on update/on delete子句, InnoDB支持5种方式, 分列如下

  

   . cascade方式

在父表上update/delete记录时,同步update/delete掉子表的匹配记录

On delete cascade从mysql3.23.50开始可用; on update cascade从mysql4.0.8开始可用

   set null方式 


1

2

3

4

5

6

7

8

9

10

在父表上update/delete记录时,将子表上匹配记录的列设为null

要注意子表的外键列不能为not null

On delete set null从mysql3.23.50开始可用; on update set null从mysql4.0.8开始可用

   . No action方式

如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作

这个是ANSI SQL-92标准,从mysql4.0.8开始支持

   . Restrict方式

同no action, 都是立即检查外键约束

删除主表中的name=Sungsum的记录。

1 engine = create_engine(‘mysql+mysqldb://root:[email protected]:3306/test‘)
2
3 DBSession = sessionmaker(bind=engine)
4 session = DBSession()
5
6 company = session.query(Company).filter_by(name="Sungsum").first()
7 session.delete(company)
8 session.commit()

默认的外键关联的动作是  “.set null”,即主表删除数据,附表中关联的字段设为空。

除了默认的设置外,还可以选择:

1、删除主表数据,如果附表有记录则不允许删除

2、删除主表数据,如果附表有记录则一并删除

回到顶部

二、外键和查询

在数据结构上外键对连表查询并没有太多的帮助,但是在sqlalchemy的模型下外键对连表查询有一定的优化,那就是relationship字段,其配合外键一起使用。

在没有relationship字段时,如果想要查询xiaomi2s手机的生产公司的地址如何查询呢?分为两步走:

  1. 查询出phone表中xiaomi2s的company_name字段
  2. 通过company_name字段查询company表中的location字段。(phone.company_name==company.name)

有了relationship之后就不用分为两步走了,只需要一步就能搞定。在定义表的模型时,relationship将company和phone表关联在一起。phone表中定义:

company_name = Column(String(32),ForeignKey("company.name"))
company = relationship("Company",backref="phone_of_company") 

表明将phone表和Company表联系在一起。backref是反向关联,使用规则是:

  1. 查询phone表,返回phone_obj,可以通过phoen_obj.Company查询到company中外键关联的数据。这个称之为:正向查询。
  2. 查询company表,返回company_obj,可以通过company_obj.phone_of_company查询到phone表的外键关联数据。这个称之为:反向查询。

1.正向查询

 1 #coding:utf-8
 2
 3 from sqlalchemy.orm import  sessionmaker
 4 from sqlalchemy import create_engine
 5 from sql_foreign import *
 6
 7
 8 engine = create_engine("mysql+mysqldb://root:[email protected]:3306/test",)
 9 Session_class = sessionmaker(bind=engine)
10 session = Session_class()
11     #查询phone表
12 phone_obj = session.query(Phone).filter_by(id = 1).first()   #通过phone表关联的relationship字段"Company"查询出company表的数据
13 print(phone_obj.company.name)
14 print(phone_obj.company.location)

通过查询phone得到company表中的字段,起作用的是relationship中的Company字段。

2.反向查询

 1 #coding:utf-8
 2
 3 from sqlalchemy.orm import  sessionmaker
 4 from sqlalchemy import create_engine
 5 from sql_foreign_models import *
 6
 7
 8 engine = create_engine("mysql+mysqldb://root:[email protected]:3306/test",)
 9 Session_class = sessionmaker(bind=engine)
10 session = Session_class()
11
12 #查询company表
13 company_obj = session.query(Company).filter_by(name = "Nokia").first()
14    #通过phone表关联的relationship的字段"backref="phone_of_company"",查询phone表数据
15 print company_obj.phone_of_company[0].id
16 print company_obj.phone_of_company[0].model
17 print company_obj.phone_of_company[0].price
18 print company_obj.phone_of_company[0].company_name

通过查询company得到phone表中的字段,起作用的是relationship中的phone_of_compamy字段。

外键还有更多操作,比如在删除主表时附表的动作。等到下次需要使用时再补上,我相信不会等太久。

原文地址:https://www.cnblogs.com/braveheart007/p/11022887.html

时间: 2024-10-06 05:21:00

sqlalchemy外键和relationship查询的相关文章

吃货眼中的sqlalchemy外键和连表查询

前言 使用数据库一个高效的操作是连表查询,一条查询语句能够查询到多个表的数据.在sqlalchem架构下的数据库连表查询更是十分方便.那么如何连表查询?以及数据库外键对连表查询有没有帮助呢?本篇文章就这两个问题简单解释. 建表 俗话说巧妇难为无米之炊,连表查询肯定要有表,有数据库啊.那有没有数据库是你见了垂涎三尺的呢?中国文化博大精深,饮食文化更是璀璨的明珠.我们就以中国菜系为话题,讲一讲好吃的,顺便再说一说外键和连表查询. 鲁菜  山东菜系,而且在明清两代,宫廷御膳是以鲁菜为主,鲁菜味道浓厚,

【Hibernate】无外键多表查询

无外键多表查询时编写hql,直接使用逗号分隔表,where作为联合查询条件进行查询.查询出来的结果可为两种,List<List<Object>>或者List<Map<String,Object>>.这时候需要使用下面语句限定查询返回结果类型. //List<Map<String,Object>> Query query = getSessionFactory().openSession().createHQLQuery(querySt

主外键多表查询demo

https://www.cnblogs.com/DragonFire/p/6949767.html mySQL练习-主外键多表查询 MySQL练习-主外键多表查询 练习: 1.建立表关系: 请创建如下表,并创建相关约束 创建表并建立表关系 表数据 补充联合唯一 2.操作练习: 1.自行创建测试数据 测试失败数据 2.查询"生物"课程比"物理"课程成绩高的所有学生的学号: 多表嵌套查询 3.查询平均成绩大于60分的同学的学号和平均成绩: HAVING用法 4.查询所有

西游之路——python全栈——ORM之SQLAlchemy(3)外键与relationship的关系

目录 relationship是为了简化联合查询join等,创建的两个表之间的虚拟关系,这种关系与标的结构时无关的.他与外键十分相似,确实,他必须在外键的基础上才允许使用 不然会报错: sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Father.son - there are no foreign keys link

Python 之 sqlalchemy 外键正反向关联查询

表内容: 代码: #Author Kang import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,ForeignKey from sqlalchemy.orm import sessionmaker,relationship #创建对象的基类

sqlalchemy外键的一些东西

数据库: 联表查询: from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,String,Integer from sqlalchemy.orm import sessionmaker engine = create_engine("mysql+pymysql://root:[email protected

SQL主、外键,子查询

主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个表只能有一个 PRIMARY KEY 约束,而且 PRIMARY KEY 约束中的列不能接受空值.由于 PRIMARY KEY 约束确保唯一数据,所以经常用来定义标识列. 主键的作用 主键的主要作用如下: (1)保证实体的完整性: (2)加快数据库的操作速度: (3) 在表中添加新记录时,数据库会自

主键、外键和子查询

1 主键和外键的区别 1.1定义 主键--唯一标识一条记录,不能有重复的,不允许为空 外键--表的外键是另一表的主键, 外键可以有重复的, 可以是空 1.2作用 主键--用来保证数据完整性 外键--用来和其他表建立联系用的 1.3个数: 主键--主键只能有一个 外键--一个表可以有多个外键 2 主键语句code int PRIMARY KEY IDENTITY(1,1), --PRIMARY KEY 标识主键--IDENTITY(1,1) 从一开始,每增加一行加一: 插入数据不用再写. 3 外键

SQL主外键和子查询

主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个表只能有一个 PRIMARY KEY 约束,而且 PRIMARY KEY 约束中的列不能接受空值.由于 PRIMARY KEY 约束确保唯一数据,所以经常用来定义标识列. 主键的作用 主键的主要作用如下: (1)保证实体的完整性: (2)加快数据库的操作速度: (3) 在表中添加新记录时,数据库会自