考虑以下Django ORM示例:
class A(models.Model):
pass
class B(models.Model):
a = models.ForeignKey('A', on_delete=models.CASCADE, null=True)
b_key = models.SomeOtherField(doesnt_really_matter=True)
class Meta:
unique_together = (('a', 'b_key'),)
现在让我们说我删除一个链接到B实例的A实例。通常,这没什么大不了的:Django可以删除A对象,设置B.a = NULL,然后在事实之后删除B。通常这很好,因为大多数数据库不会在唯一约束中考虑NULL值,因此即使您拥有b1 = B(a=a1, b_key='non-unique')
和b2 = B(a=a2, b_key='non-unique')
,并且同时删除了a1
和a2
,这不是问题,因为(NULL, 'non-unique') != (NULL, 'non-unique')
是因为NULL != NULL
。
不过,that's not the case with SQL Server。 SQL Server出色地定义了NULL == NULL
,这打破了这一逻辑。 The workaround, if you're writing raw SQL, is to use WHERE key IS NOT NULL
定义唯一约束时,但这是Django为我生成的。虽然我可以手动创建RunSQL迁移,但我需要删除所有原始的唯一约束并添加新的过滤约束,但这绝对是ORM或驱动程序的缺点(我使用的是pyodbc + django-pyodbc-azure)。是否可以通过某种方式哄骗Django首先生成经过过滤的唯一约束,或者以某种顺序强制其删除表以完全规避此问题,或者可以将其他一些常规解决方法应用于SQL Server?