sqlalchemy外键和relationship查询

前面的文章中讲解了外键的基础知识和操作,上一篇文章讲解了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:123@localhost: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中不存在该值,所以不能写入。这样做就保证了数据的完整性。

 

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

外键约束对父表的含义:在父表上进行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方式 
在父表上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:123@localhost: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:123@localhost: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:123@localhost: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/goldsunshine/p/9269880.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/485709.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

加大基础研究投入 给科技创新注入“强心剂”

来源:科技日报进一步加大政府科技投入力度,引导社会各界对基础研究的投入与布局,健全鼓励支持基础研究、原始创新的体制机制,探索多元化财政科技投入方式,完善鼓励研发投入的政策体系,提升科技经费投入的有…

Gym - 100989J -(DFS)

题目链接:http://codeforces.com/gym/100989/problem/J J. Objects Panel (A)time limit per test1.0 smemory limit per test256 MBinputstandard inputoutputstandard outputRaihan is helping Maram and Master Hasan in the design of their graduation project…

艰难2020:人工智能的应用是否已停滞不前?

作者:Gary Grossman译者:Sambodhi策划:刘燕今年,每一个季度都是疯狂的一年,人工智能的发展同样如此。总的来说,这一年人工智能的发展喜忧参半,其中有显著的进展,也有对技术滥用的新发…

浅谈WM算法

1. WM(Wu-Manber)算法的简单理解:(1)WM算法需要的参数:∑:字母集c: 字母集数目m:模式串集合中,字符串长度最小的模式串的长度B:字符块长度&#…

AI研习丨专题:因果推断与因果性学习研究进展

来源:《中国人工智能学会通讯》2020年 第10卷 第5期 机器学习及其应用专题0 引言因果关系一直是人类认识世界的基本方式和现代科学的基石。爱因斯坦就曾指出,西方科学的发展是以希腊哲学家发明形式逻辑体系,以及通过系统的实验发现有可能找…

传感器的未来: 10年后我们将会生活在一个极端透明的世界

来源:大数据文摘作者:彼得戴曼迪斯2014年,在芬兰的一个传染病实验室里,卫生研究员佩特里拉特拉(Petteri Lahtela)发现了一件奇怪的事情,他突然意识到他所研究的很多问题的条件都存在着重叠。例如…

企业计算机服务器中了babyk勒索病毒怎么办,babyk勒索病毒解密数据恢复

在数字化的今天,网络安全威胁不断增加,给企业的生产生活带来了严重影响,使得企业不得不重视数据安全问题。近日,云天数据恢复中心接到企业求助,企业的计算机服务器中了babyk勒索病毒,导致企业所有计算机系统…

java yied的用法,Java多线程的wait(),notify(),notifyAll()、sleep()和yield()方法使用详解,...

Java多线程的wait(),notify(),notifyAll()、sleep()和yield()方法使用详解,Java多线程中的wait(),notify(),notifyAll()、sleep()和yield()方法我们先从一个案例开始:static public class WaitingTest {//s…

海马体启发的记忆模型

来源:混沌巡洋舰 记忆是人类智能的关键,我们因为记忆可以把过去和当下整合成为一体, 并且可以预测未来。记忆不仅是一个信息承载的工具, 更是世界模型的本体, 它无时无刻不在刻画未来, 也被当下影响&#…

DeepMind最新发现!神经网络的性能竟然优于神经符号模型

来源:深度学习这小事按照之前的常识,结合了算法和符号推理技术的神经符号模型(Neurosymbolic Models),会比神经网络更适合于预测和解释任务,此外,神经符号模型在反事实方面表现更好。而Neural-S…

刚刚Sci-Hub和特朗普一样被永久封禁,Twitter官方:不得上诉

来源:量子位晓查 发自 凹非寺 公众号:QbitAI今天,Twitter官方宣布永久封禁特朗普的账号。而另一个账号的封禁恐怕更让科学界感到震惊。有用户发现,Sci-Hub的Twitter账号和特朗普一样,都被完全清空了。随后,…

javaweb简要介绍,虚拟路径,虚拟主机

1. 静态,动态:是否随时间,地点,用户操作的改变而改变 动态网页 需要使用到 服务端脚本语言(JSP) 2. 架构: CS: Client Server eg:qq,微信,cs游戏 不足: 1.如果软…

物理学中的不确定性

来源:人机与认知实验室吴骏(香港中文大学通识教育基础课程讲师)【物理研究的只是模型,而不是真理】物理学中的确定性问题缘起于我正在教授的《与自然对话》[1] 这门课。其中节选了詹姆士华生 (James Watson) 在2003年写的一本畅销…

JSP执行流程

第一次访问:服务端将jsp翻译成java,再将Java编译成class文件 第二次访问:直接访问class文件较快,所以第一次访问比较慢,以后就快了 (如果服务器代码修改了,则需要重新进行翻译,编译…

玩电子游戏的神经网络,告诉我们大脑是如何决策的

来源:混沌巡洋舰当你开车的时候,你的大脑会接收大量的视觉信息,并用它来做出驾驶的决定,比如什么时候刹车或者换车道。大脑需要决定在你的视野中哪些信息是做出这些决定所必需的。例如,另一辆车的位置是非常重要的&…

2021年的第一盆冷水:有人说别太把图神经网络当回事儿

来源:数学中国图神经网络(GNN)是机器学习中最热门的领域之一,在过去短短数月内就有多篇优秀的综述论文。但数据科学家 Matt Ranger 对 GNN 却并不感冒。他认为这方面的研究会取得进展,但其他研究方向或许更重要。博客链…

JSP页面元素,内置对象及request详解

JSP的页面元素&#xff1a; a. 脚本Scriptlet 1.<% 局部变量&#xff0c;Java语句 %> 2.<%! 全局变量&#xff0c;定义方法 %> 3.<% 输出表达式 %> 一般而言&#xff0c;修改web.xml&#xff0c;配置文件&#xff0c;Java&#xff0c;需要重启tomcat服务&am…

美国科学院报告《无止境的前沿:科学的未来75年》

来源&#xff1a;科技咨询频道作者&#xff1a;刘昊 张志强 曹玲静编译&#xff1a;刘昊 张志强 曹玲静 &#xff08;中国科学院成都文献情报中心&#xff09;2020年12月17日&#xff0c;美国国家科学院出版报告《无止境的前沿——科学的未来75年》&#xff08;The Endless Fro…

jsp内置对象--response

response&#xff1a;响应对象 提供的方法&#xff1a;void addcookie(Cookie cookie);服务端向客户端增加一个cookie对象 void sendRedirect(String location) throws IOException:页面跳转的一种方式&#xff08;重定向&#xff09; void setContetType(String type) :设置…

AR增强现实技术解读

来源&#xff1a;网络 AR增强现实&#xff0c;是用户对现实世界感知的新技术。一般认为&#xff0c;AR技术的出现源于虚拟现实技术&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;的发展&#xff0c;但二者存在明显的差别。传统VR技术给予用户一种在虚拟世界中完全…