【SQLAlChemy】表之间的关系,外键如何使用?

表之间的关系

数据库表之间的关系分为三种:

  • 一对一关系(One-to-One):在这种关系中,表A的每一行都与表B的一行关联,反之亦然。例如,每个人都有一个唯一的社保号,每个社保号也只属于一个人。
  • 一对多关系(One-to-Many):在这种关系中,表A的一行可以与表B的多行关联,但表B的每一行只能与表A的一行关联。例如,一位母亲可以有多个孩子,但每个孩子只能有一个生物学上的母亲。
  • 多对多关系(Many-to-Many):在这种关系中,表A的一行可以与表B的多行关联,表B的一行也可以与表A的多行关联。例如,一个学生可以选修多门课程,一门课程也可以被多个学生选修。

在数据库中,这些关系通常通过使用外键(Foreign Key)来建立。

外键

外键(Foreign Key)是一种特殊类型的数据库约束,主要用于创建表之间的链接或关系。

外键是在一个表中创建的,它是另一个表的主键(Primary Key)。这个外键用来指向另一个表的主键,从而建立两个表之间的关系。

外键的主要目的是维护数据的引用完整性。这意味着,如果试图在一个表中插入一行,而这行数据的外键值在相关表中不存在,数据库将不允许这个操作。同样,如果试图删除一个表中的行,而这行数据的主键在其他表中作为外键存在,那么数据库也不会允许这个删除操作,除非先删除或更改引用这个主键的所有外键。

例如,假设有两个表,一个是学生表,一个是课程表。每个学生可以注册多个课程,所以在课程表中,可能会有一个列叫做 "student_id",这个列是学生表的外键。这样,就可以通过学生的 ID 查询他们注册的所有课程,同时也保证了每个课程都有一个注册的学生。

使用 SQLAlchemy 创建外键的步骤:

  1. 定义表格:首先,需要定义数据库表格。每个表格对应一个 SQLAlchemy 类,类中的每个属性对应表格中的一个列。
  2. 设置外键:在定义表格的过程中,可以使用 ForeignKey 函数来设置外键。ForeignKey 函数的参数是想要链接的表格的列名。例如,如果有一个 Order 表,想让它链接到 Customer 表的 id 列,可以这样写: customer_id = Column(Integer, ForeignKey('customer.id'))
  3. 创建关系:在设置了外键之后,还需要在 SQLAlchemy 类中使用 relationship 函数来创建两个表格之间的关系。例如,可以在 Customer 类中添加如下的代码: orders = relationship("Order", backref="customer")。 这段代码表示一个客户可以有多个订单,每个订单都有一个关联的客户。
  4. 创建数据库:最后,需要使用 SQLAlchemy 的 create_all 函数来创建数据库。这个函数会根据定义的 SQLAlchemy 类来创建表格,并设置好所有的外键和关系。

实例

实现学生 StudentLesson 之间的关系表的建立。

python 代码:

Base = declarative_base()# 定义 Student 表
class Student(Base):__tablename__ = 'student'id = Column(Integer, primary_key=True)name = Column(String(50), nullable=False)age = Column(Integer)def __repr__(self):return "<Student(name='%s', age='%s')>" % (self.name, self.age)# 定义 Lesson 表
class Lesson(Base):__tablename__ = 'lesson'id = Column(Integer, primary_key=True)name = Column(String(50), nullable=False)description = Column(String(100), nullable=False)student_id = Column(Integer, ForeignKey('student.id'))def __repr__(self):return "<Lesson(name='%s', description='%s')>" % (self.name, self.description)Base.metadata.create_all(engine)

sql语句代码:

create table student
(id   int auto_incrementprimary key,name varchar(50) not null,age  int         null
);create table lesson
(id          int auto_incrementprimary key,name        varchar(50)  not null,description varchar(100) not null,student_id  int          null,constraint lesson_ibfk_1foreign key (student_id) references student (id)
);create index student_idon lesson (student_id);

表关系图:

测试插入数据:

# 测试插入数据# Student 数据
stu1 = Student(name='zmz', age=10)
stu2 = Student(name='ypb', age=18)
stu3 = Student(name='gll', age=20)session.add_all([stu1, stu2, stu3])
session.commit()# Lesson 数据
l1 = Lesson(name='java', description='this is java', student_id=stu1.id)
l2 = Lesson(name='java', description='this is java', student_id=stu2.id)
l3 = Lesson(name='python', description='this is python', student_id=stu1.id)
session.add_all([l1, l2, l3])
session.commit()

数据库 student 表:

数据库 lesson 表:

外键约束分类

  • RESTRICT:这是默认选项。当尝试删除父表中的数据时,如果子表中存在与之关联的数据,那么这个删除操作将会被阻止。也就是说,只有当没有任何子表行与父表行关联时,才能删除父表中的行。
  • NO ACTION:在 MySQL 中,这个选项的行为与 RESTRICT 选项相同。也就是说,如果子表中存在与父表行关联的行,那么尝试删除父表中的行将会被阻止。
  • CASCADE:这个选项表示级联删除。当你删除父表中的行时,所有在子表中与之关联的行也会被自动删除。这种选项需要谨慎使用,因为它可能会导致大量的数据被删除。
  • SET NULL:当父表中的行被删除时,这个选项会将子表中所有与之关联的行的外键列设置为 NULL。这意味着,子表中的这些行不再与父表中的任何行关联。注意,为了使用这个选项,子表的外键列必须允许 NULL 值。

修改 lesson 表:

# 定义 Lesson 表
class Lesson(Base):__tablename__ = 'lesson'id = Column(Integer, primary_key=True)name = Column(String(50), nullable=False)description = Column(String(100), nullable=False)student_id = Column(Integer, ForeignKey('student.id', ondelete='CASCADE'), nullable=False)def __repr__(self):return "<Lesson(name='%s', description='%s')>" % (self.name, self.description)

注意事项

问题:

加入在添加数据时,我们先提交了 student 中的数据,之后在提交了 lesson 中的数据,会造成 lessonstudent_id 为空。

分析:

在 SQLAlchemy 中,当使用 session.add() 方法时,数据并不会立即被写入数据库,而是被添加到了会话的事务队列中。只有当调用 session.commit() 方法时,才会将这些变更写入数据库。在这之前,新创建的 Student 对象的 id 属性是 None,因为它们还没有被分配数据库中的 id

在代码中,首先创建了几个 Student 对象,并使用 session.add_all() 添加到会话中,但是在添加 Lesson 对象之前,没有调用 session.commit()。因此,当试图访问 stu1.id 时,它其实是 None,这就是为什么在插入 Lesson 数据时会出现错误。
为了解决这个问题,需要在添加 Lesson 对象之前,先提交 Student 对象。

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

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

相关文章

南师大GIS专业2024排名NO.1!!!

南师大GIS 666 学科专业实力666&#xff0c;研究方向多多多&#xff01; 有学术方向有开发应用方向&#xff0c; 有GIS&#xff08;建模、数字地形、基础理论和三维GIS等&#xff09;、 有Cartography &#xff08;叙事地图、动态地图、地图风格迁移等&#…

Visual Studio Code 的安装教程和配置C语言环境插件推荐

目录 1.vscode简介2.下载安装vs code3.VSCode基础配置VSCode界面简介VSCode设置中文界面VSCode个性化设置VSCode常用设置基本编辑快捷键VSCode常用快捷键 4.下载安装MinGW5.设置vscode里的环境6.插件推荐7.vscode官方文档 1.vscode简介 VSCode是微软出的一款轻量级编辑器&…

Javaweb03-Servlet技术1(Servlet,ServletConfig,ServletContext)

Servlet技术(Servlet,ServletConfig,ServletContext) 1.Servlet的概述 Servlet是运行在Web服务器端的Java应用程序&#xff0c;它使用Java语言编写。与Java程序的区别是&#xff0c;Servlet 对象主要封装了对HTTP请求的处理&#xff0c;并且它的运行需要Servlet容器(Tomcat)的…

人工智能历史与现状

1 人工智能历史与现状 1.1 人工智能的概念和起源 1.1.1 人工智能的概念 人工智能 (Artificial Intelligence ,AI)是一门研究如何使计算机 能够模拟人类智能行为的科学和技术,目标在于开发能够感知、理解、 学习、推理、决策和解决问题的智能机器。人工智能的概念主要包含 以…

vivado HW_TARGET

HW_目标 描述 硬件目标hw_target是包含一个或多个JTAG链的系统板 Xilinx FPGA设备&#xff0c;您可以使用比特流文件进行编程&#xff0c;或用于调试您的设计。 系统板上的硬件目标与Vivado Design Suite之间的连接 由硬件服务器对象hw_server管理。 使用open_hw_target命令打开…

StableSwarmUI 安装教程(详细)

文章目录 背景特点安装 背景 StableSwarmUI是StabilityAI官方开源的一个文生图工作流UI&#xff0c;目前处于beta阶段&#xff0c;但主流程是可以跑通的。该UI支持接入ComfyUI、Stable Diffusion-WebUI。其工作原理就是使用ComfyUI、Stable Diffusion-WebUI或者StabilityAI官方…

利用系统或软件缺陷进行攻击

操作系统都有漏洞 这里就是输入的字符串长度太长了 超过8个字节了 没听懂

在下游市场需求带动下 我国聚天门冬氨酸脂防腐涂料市场规模不断扩大

在下游市场需求带动下 我国聚天门冬氨酸脂防腐涂料市场规模不断扩大 聚天门冬氨酸酯防腐涂料又称为天冬聚脲防腐涂料&#xff0c;是以聚天门冬氨酸酯作为主体树脂、脂肪族异氰酸酯为固化剂而形成的一种防腐涂料。与其他类型的防腐涂料相比&#xff0c;聚天门冬氨酸酯防腐涂料具…

【Hive下篇: 一篇文章带你了解表的静态分区,动态分区! 分桶!Hive sql的内置函数!复杂数据类型!hive的简单查询语句!】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本篇文章主要分享的是大数据开发中hive的相关技术。连接查询&#xff01;正则表达式&#xff01; 虚拟列&#xff01;爆炸函数&#xff01;行列转换&#xff01; Hive的数据压缩和数据存储…

利用穿戴甲虚拟试戴技术提高销量和参与度

在不断变化的美容行业&#xff0c;保持领先意味着拥抱创新技术。其中一项改变游戏规则的技术是人工智能驱动的虚拟指甲试戴。在穿戴甲领域&#xff0c;不断兴起的虚拟试戴技术对促进销售和参与度产生了重大影响。 视觉吸引力的力量 要了解虚拟试戴的重要性&#xff0c;必须了解…

简单了解MySql以及一些简单的应用MySql

MySql基础篇 1、数据模型概述 关系型数据库 概念&#xff1a;建立在关系模型基础上&#xff0c;由多张相互连接的二维表组成的数据库。 特点&#xff1a; 使用表存储数据&#xff0c;格式统一&#xff0c;便于维护使用SQL语言操作&#xff0c;标准统一&#xff0c;使用方便 数…

基于hispark_taurus开发板示例学习OpenHarmony编译构建系统(2)

3、hispark_taurus产品解决方案-Vendor 产品解决方案为基于开发板的完整产品&#xff0c;主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为&#xff1a;vendor/{产品解决方案厂商}/{产品名称}_。_产品解决方案也是一个特殊的组…

vue生命周期及组件讲解(如何导入引用外部vue文件,以及注册全局变量,自定义标签效果)

生命周期钩子的理解与应用 函数说明onBeforeMount( )组件挂载前onMounted( )组件挂载后onBeforeUpdate( )组件更新前onUpdated( )组件中任意的DOM元素更新后onBeforeUnmount( )组件实例被销毁前onUnmounted( )组件实例被销毁后 生命周期在 各类应用以及网站中使用非常广泛&…

k8s+springboot+redis部署配置连接

1 springboot 配置k8s中的redis服务名 #tomcat访问端口 # 应用名称 spring.application.namedemo # 应用服务Web访问端口 server.port8089 server.envtest #缓存关闭 spring.thymeleaf.cachefalse #可选配置 management.endpoints.enabled-by-defaulttrue management.endpoint…

springboot与flowable(6):任务分配(监听器)

一、创建流程模型 制作如下流程 给审批用户1一个值表达式。 二、给用户审批2添加监听器 创建一个监听器类 package org.example.flowabledemo2.listener;import org.flowable.engine.delegate.TaskListener; import org.flowable.task.service.delegate.DelegateTask;/*** 自定…

【PLG洞察】|向Figma学习如何打造标杆客户和实施分销策略

Figma是一款功能强大的在线协同设计工具&#xff0c;它主要被用于界面设计、原型设计和用户体验设计。作为国外知名的saas企业&#xff0c;对标国内的saas蓝海&#xff0c;它的增长实在惊人&#xff01;据称&#xff0c;Figma2020年的收入已达$75M, 2021年6月&#xff0c;美国的…

springSecurity学习笔记(一)

简介 Spring Security是一个Java框架&#xff0c;用于保护应用程序的安全性。它提供了一套全面的安全解决方案&#xff0c;包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念&#xff0c;可以轻松地集成到任何基于Spring的应用程序中。它支持多种身份验…

海洋CMS /js/player/dmplayer/dmku/ SQL注入漏洞复现(CVE-2024-29275)

0x01 产品简介 海洋CMS是一套专为不同需求的站长而设计的内容管理系统&#xff0c;灵活、方便、人性化设计、简单易用是最大的特色&#xff0c;可快速建立一个海量内容的专业网站。海洋CMS基于PHPMySql技术开发&#xff0c;完全开源免费 、无任何加密代码。 0x02 漏洞概述 海…

Jsch上传本地目录文件到服务器

文章目录 1.Jsch简介1.1 什么是Jsch1.2 Jsch使用步骤和简单示例 2.技术关键点3.Jsch实战3.1 maven依赖3.2 功能实现3.3 效果3.4 封装工具类 4.总结 摘要: 在一些框架开发工作中&#xff0c;需要为项目使用说明文档&#xff0c;来指导用户如何正确使用框架。比如通过markdown编写…

一文搞懂阻塞赋值和非阻塞赋值

目录 2.非阻塞赋值举例3.阻塞赋值举例4.总结 微信公众号获取更多FPGA相关源码&#xff1a; # 1.阻塞赋值和非阻塞赋值的区别&#xff1a; (1)阻塞赋值""&#xff0c;必须是阻塞赋值完成后&#xff0c;才进行下一条语句的执行&#xff1b;赋值一旦完成&#xff0c;等号…