foreign key 说明

本文介绍了MySQL中外键的应用,包括如何创建外键约束以确保参照完整性,并通过实例演示了外键如何阻止非法数据插入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 自己的代码总提示“ERROR 1005: Can't create table (errno: 150)”的错误郁闷了好几天,看了下面的文章终于成功了,犯了下面提到的三情况中的第三种,太不细心了,居然忽略了“UNSIGNED ”,大家也要多留意呀!!  
  2.   
  3. 参照完整性(Referentialintegrity)是数据库设计中一个重要的概念。在系统不同的列表中,当数据库所有参照合法或非合法关联时都会涉及到参照完整性。当参照完整性存在时,任何与不存在记录的关联将变得无效化,由此可防止用户出现各种错误,从而提供更为准确和实用的数据库。   
  4.   
  5.   参照完整性通常通过外键(foreign key)的使用而被广泛应用。长久以来,流行工具开源RDBMSMySQL并没有支持外键,原因是这种支持将会降低RDBMS的速度和性能。然而,由于很多用户对参照完整性的优点倍感兴趣,最近MySQL的不同版本都通过新InnoDB列表引擎支持外键。由此,在数据库组成的列表中保持参照完整性将变得非常简单。   
  6.   
  7.   为了建立两个MySQL表之间的一个外键关系,必须满足以下三种情况:   
  8.   
  9.     * 两个表必须是InnoDB表类型。   
  10.     * 使用在外键关系的域必须为索引型(Index)。   
  11.     * 使用在外键关系的域必须与数据类型相似。   
  12.   
  13. 例子是理解以上要点的最好方法,新建一个parts的表,cpu字段用来存放所有的cpu配件型号,再新建一个pc的表,其中的cpumodel字段用来存放pc机中的cpu型号,显然,cpumodel字段中的所有记录应该存在于parts表中。   
  14. mysql> create table parts(   
  15.     -> cpu char(20) not null,   
  16.     -> index(cpu)   
  17.     -> )engine=innodb;   
  18. Query OK, 0 rows affected (0.01 sec)   
  19.   
  20. mysql> create table pc(   
  21.     -> cpumodel char(20) not null,   
  22.     -> index(cpumodel),   
  23.     -> foreign key(cpumodel) references parts(cpu)   
  24.     -> )engine=innodb;   
  25. Query OK, 0 rows affected (0.01 sec)   
  26.   
  27. 注意:对于非InnoDB表, FOREIGN KEY 语句将被忽略。对parts表添加数据123,接着对pc表进行测试,满足条件的 1 可以顺利insert进去,而不符合条件的字符 5 在insert表的时候,出现外键约束性错误,这正是我们想要的结果   
  28.   
  29.   
  30. mysql> insert into parts values('1'),('2'),('3');   
  31. Query OK, 3 rows affected (0.00 sec)   
  32. Records: 3  Duplicates: 0  Warnings: 0   
  33.   
  34. mysql> insert into pc values('1');   
  35. Query OK, 1 row affected (0.01 sec)   
  36.   
  37.   
  38. mysql> insert into pc values('5');   
  39. ERROR 1452 (23000): Cannot add or update a child row: a foreign   
  40. key constraint fails (`Orange/pc`, CONSTRAINT `pc_ibfk_1` FOREIGN KEY   
  41. (`cpumodel`) REFERENCES `parts` (`cpu`))   
  42.   
  43.   
  44. 如以上例子解释的,外键在捉摸数据入口错误上起着重要的作用,由此可建立更为强健更加集成的数据库。另一方面值得提到的是,执行外键核实是内部资料处理的过程,且不同表之间指定复杂的内部关系可以导致数据库的性能下降。所以,在参照完整性与性能考虑之间找到平衡点相当重要,而使用外键就是能够确保性能与稳健之间的最优结合。  我期望本期的有关外键的介绍对你有所好处,你将会在下回的MySQL数据库设计中感受到外键的好处。编程快乐!
### Django 中 `ForeignKey` 函数的使用说明 #### 一、`ForeignKey` 的基本概念 `ForeignKey` 是 Django ORM 提供的一种字段类型,用于表示两个模型之间的一对多关系。这种关系意味着一个父级记录可以拥有多个子级记录,而每个子级记录只属于一个父级记录[^3]。 例如,在书籍管理系统中,一本书可能只有一个作者,但一位作者可能会写多本书。因此,`Book` 模型可以通过 `ForeignKey` 关联到 `Author` 模型。 --- #### 二、`ForeignKey` 的标准语法 以下是 `ForeignKey` 字段的基本定义方式: ```python class ModelName(models.Model): field_name = models.ForeignKey( RelatedModel, on_delete=models.CASCADE, related_name='optional_reverse_relation', null=False, blank=False, db_column='optional_db_column' ) ``` - **RelatedModel**: 表示与当前模型建立外键关系的目标模型。 - **on_delete**: 当关联的对象被删除时的行为选项。常见值包括: - `models.CASCADE`: 删除关联对象时也删除依赖该对象的其他对象。 - `models.PROTECT`: 防止删除关联对象。 - `models.SET_NULL`: 将外键字段设为 NULL(前提是允许 NULL)。 - `models.SET_DEFAULT`: 设置默认值。 - `models.DO_NOTHING`: 不采取任何行动。 - **related_name**: (可选)指定从目标模型反向查询当前模型的关系名称。 - **null**: (布尔值,默认 False)是否允许数据库层面存储 NULL 值。 - **blank**: (布尔值,默认 False)是否允许表单验证时为空。 - **db_column**: (可选)自定义数据库中外键列的名字。 --- #### 三、实际案例分析 ##### 1. 定义模型并创建外键关系 以下是一个简单的例子,展示如何在 `Book` 和 `Author` 模型间建立外键关系[^3]: ```python from django.db import models class Author(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey(Author, on_delete=models.CASCADE) def __str__(self): return f"{self.title} by {self.author}" ``` 在这个例子中,每本 `Book` 都有一个唯一的 `author`,而每位 `Author` 可能有多本书籍。 --- ##### 2. 数据库操作演示 利用上述模型,我们可以通过以下代码进行数据交互: ###### 创建和保存对象 ```python # 创建一个新的作者 author = Author(name="J.K. Rowling") author.save() # 创建一本新书,并将其绑定到特定作者 book = Book(title="Harry Potter and the Sorcerer's Stone", author=author) book.save() ``` ###### 查询相关数据 通过外键关系,可以从任意一侧轻松访问另一侧的数据[^4]: - 获取某位作者的所有书籍: ```python books_by_author = author.book_set.all() # 使用 default reverse relation 名称 for book in books_by_author: print(book.title) ``` - 或者显式指定 `related_name` 后更直观地访问: ```python class Book(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books') # 访问更加语义化的方式 books_by_author = author.books.all() ``` --- ##### 3. 性能优化技巧 在外键场景下,频繁触发 N+1 查询可能导致性能瓶颈。为此,Django 提供了两种主要机制来解决这一问题:`select_related` 和 `prefetch_related`[^1]。 - **`select_related`**: 适用于单一或嵌套外键链路的情况,能够提前加载所需的相关数据。 ```python authors_with_books = Author.objects.select_related('book').all() for author in authors_with_books: print(author.book.title) # 已经预取,不会再次发起 SQL 查询 ``` - **`prefetch_related`**: 适合处理多对多或多对外键集合的情形,批量获取所有关联项。 ```python authors_with_all_books = Author.objects.prefetch_related('book_set').all() for author in authors_with_all_books: for book in author.book_set.all(): print(book.title) # 批量预取,减少重复查询次数 ``` --- #### 四、注意事项 - 正确设置 `on_delete` 参数非常重要,因为它决定了当父级对象被移除时会发生什么行为。 - 如果需要双向导航能力,请考虑添加合适的 `related_name` 属性以增强代码可读性和逻辑清晰度。 - 在大规模生产环境中务必关注潜在的性能隐患,适时运用 `select_related` 或 `prefetch_related` 方法降低开销。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值