现状
以Django 3.2为例
Django ORM 设计为默认使用单一主键(通常是自增的 id
字段),这一选择主要基于以下核心原因:
- 简化ORM设计与操作
- 统一访问方式
- 外键关联简化
- 避免歧义冲突
- 主键语义明确
- 防止隐式依赖
- 性能与数据库兼容
- 索引效率优化
- 跨数据库兼容
- 替代方案成熟
- unique_together约束
Oracle现状
原始业务表,很多都使用多主键。
使用Django映射现有Oracle数据库无法处理多主键问题。
Oracle表结构 & Django Model
示例(库存表,使用多主键):
字段 | 主键 |
item_no | True |
warehouse | True |
location | True |
quantity | False |
此时,使用Django Inspectdb将该表结构映射到Models文件中,只有item_no字段被设置为primary key,然后使用unique_together的方式来做组合值唯一性控制。这样是存在问题的。
class InventoryDetail(models.Model):item_no= models.CharField(primary_key=True, max_length=15)warehouse = models.CharField(max_length=6)location = models.CharField(max_length=6)quantity = models.DecimalField(max_digits=18, decimal_places=6, blank=True, null=True)class Meta:managed = Falsedb_table = 'inventory_detail'unique_together = (('item_no', 'warehouse', 'location'),)
解决方案
- 使用Oracle不可见字段 INVISIBLE,Oracle12以及以上
- 为表创建不可见字段id,字段名自定义:
alter table inventory_detail add (id int invisible generated as identity)
- 不可见字段默认不会出现在select * 结果中,因此不影响现有系统对该表的使用。
- 使用了generated as identity,会自动对原始数据的id字段赋值,新插入的数据也会自动赋值。且无法Update该字段的值
- 为表创建不可见字段id,字段名自定义:
- Django数据库映射
- 使用inspectdb将表结构映射到models文件时,不可见字段无法写入到文件。
- 因此需要手动将该字段添加到model中
- id = models.BigAutoField(primary_key=True)
- unique_together正常情况下会字段写入,可以不用处理
- 然后就可以用了
技术细节
Oracle invisible(不可见字段)
Django ORM
小结
目前基本的测试没问题