是否可以在数据库中为外键创建唯一的字段?
Posted
技术标签:
【中文标题】是否可以在数据库中为外键创建唯一的字段?【英文标题】:Is possible to make unique a field in the database for a foreign key? 【发布时间】:2021-06-28 22:48:29 【问题描述】:假设我有两个模型,分别命名为 Company 和 Airplane:
class Company(models.Model):
name= models.CharField(max_length=250)
location=models.Charfield(max_length=250)
class Airplane(models.Model):
company = models.ForeignKey(Company, on_delete=models.RESTRICT)
number = models.IntegerField(unique=True)
我希望飞机型号中的编号是唯一的,但只是在同一家公司,另一家公司的飞机可以有相同的编号。这可能吗?
【问题讨论】:
【参考方案1】:您可以强制执行多列唯一性约束,而不是要求飞机编号字段是唯一的。换句话说,(company, number) 对应该是唯一的,并且另一个默认的自动递增列可以用作 Airplane 表的主键。
在此处查看答案: How to define two fields "unique" as couple
【讨论】:
【参考方案2】:您可以为由 company 和 number 列组成的飞机表创建一个 UNIQUE Index(至少在本机 SQLite 中)。
我没有使用过 Django,所以我不确定是否可以使用多列索引。
看来您可以按照Django composite unique on multiple model fields 在DJango 中使用unique_together
或
UniqueConstraint
https://docs.djangoproject.com/en/3.1/ref/models/constraints/#django.db.models.UniqueConstraint
但是,对于本机 SQLite 代码,这里有一些演示基本原理/操作的代码:-
DROP INDEX IF EXISTS airplane_number_company;
DROP TABLE IF EXISTS airplane;
DROP TABLE IF EXISTS company;
CREATE TABLE IF NOT EXISTS company (name TEXT UNIQUE, location TEXT);
CREATE TABLE IF NOT EXISTS airplane (company REFERENCES company(name), number INTEGER);
CREATE UNIQUE INDEX IF NOT EXISTS airplane_number_company ON airplane(company,number);
INSERT INTO company VALUES('company1','England'),('company2','America');
INSERT INTO airplane VALUES('company1',100),('company1',200),('company2',100),('company2',200);
SELECT * FROM airplane JOIN company ON airplane.company = company.name;
INSERT OR IGNORE INTO airplane VALUES('company1',100),('company1',500);
SELECT * FROM airplane JOIN company ON airplane.company = company.name;
第一个 SELECT 将显示已添加的 4 行,表明可以添加具有相同编号但不同公司的飞机。
在选择之后尝试插入两个新的飞机行。一行使用与现有飞机相同的公司和编号,另一行使用未使用的组合。
然后第二个 SELECT 显示结果,表明仅添加了两行中的 1 行。由于 airplane_number_company 索引 OR IGNORE
允许忽略失败的尝试,因此无法添加第一行。
上面运行的日志是:-
DROP INDEX IF EXISTS airplane_number_company
> OK
> Time: 0s
DROP TABLE IF EXISTS airplane
> OK
> Time: 0s
DROP TABLE IF EXISTS company
> OK
> Time: 0s
CREATE TABLE IF NOT EXISTS company (name TEXT UNIQUE, location TEXT)
> OK
> Time: 0.11s
CREATE TABLE IF NOT EXISTS airplane (company REFERENCES company(name), number INTEGER)
> OK
> Time: 0.096s
CREATE UNIQUE INDEX IF NOT EXISTS airplane_number_company ON airplane(company,number)
> OK
> Time: 0.085s
INSERT INTO company VALUES('company1','England'),('company2','America')
> Affected rows: 2
> Time: 0.073s
INSERT INTO airplane VALUES('company1',100),('company1',200),('company2',100),('company2',200)
> Affected rows: 4
> Time: 0.074s
SELECT * FROM airplane JOIN company ON airplane.company = company.name
> OK
> Time: 0.001s
INSERT OR IGNORE INTO airplane VALUES('company1',100),('company1',500)
> Affected rows: 1
> Time: 0.082s
SELECT * FROM airplane JOIN company ON airplane.company = company.name
> OK
> Time: 0s
【讨论】:
以上是关于是否可以在数据库中为外键创建唯一的字段?的主要内容,如果未能解决你的问题,请参考以下文章