Рассмотрим следующий пример 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'),)
Теперь предположим, что я удаляю экземпляр A, связанный с экземпляром B. Обычно это не так уж и сложно: 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
.
Однако это не так с SQL Server . SQL Server блестяще определяет NULL == NULL
, что нарушает эту логику. Обходной путь, если вы пишете необработанный SQL, должен использовать WHERE key IS NOT NULL
при определении ограничения уникальности, но это сгенерировано для меня Django. Несмотря на то, что я могу вручную создавать миграции RunSQL, которые мне понадобятся, чтобы удалить все оригинальные уникальные ограничения и добавить новые отфильтрованные, это определенно является недостатком ORM или драйвера (я использую pyodbc + django-pyodbc-azure). Есть ли какой-нибудь способ либо заставить Django генерировать отфильтрованные уникальные ограничения в первую очередь, либо заставить его удалять таблицы в определенном порядке, чтобы вообще обойти эту проблему, или какое-то другое общее исправление, которое я мог бы применить к серверу SQL?