我正在尝试学习如何使用 Django 的 ORM 进行更高级的查询,而不是使用原始 sql。
select_related
进行连接以减少数据库命中,原则上它可以进行我手动执行的连接。
但有一个问题:它不使用反向外键关系来制作sql。对于我的架构来说,这是一个麻烦。我发现了一种看起来非常简单的解决方法,但我担心它会以我不理解的方式出现错误。
我使用的是旧版数据库,它是只读的,因此不受 ORM 管理,并且级联设置不会产生任何后果。我通过manage.py analysisdb为其表制作了模型,效果非常好;我有一个 6000 行的模型文件,只需要花十分钟就可以修复。
我所做的一个调整是一种欺骗select_related
通过创建外键关系,实际上是反向 FK 关系。这意味着我的模型中有两个条目指向同一数据库列,这是主键(正确),现在也是外键。我利用了“新”专栏select_related
.
我的查询的主表是 Service。它与许多其他表具有外键关系,并且与 select_lated 配合使用效果很好。
servrecid_1 列是我人为添加的。另外两列是两列真正的 FK;还有更多。
class Service(models.Model):
servrecid = models.AutoField(db_column='ServRecID', primary_key=True)
servrecid_1 = models.ForeignKey('RecServ', models.DO_NOTHING, to_field='servrecid',
db_column='ServRecID') # Field name made lowercase.
visitrecordid = models.ForeignKey('Visit', models.DO_NOTHING, db_column='VisitRecordID', blank=True,
null=True) # Field name made lowercase.
itemno = models.ForeignKey(Fees, models.DO_NOTHING, db_column='ItemNo', to_field='itemno')
...
class Meta:
managed = False # same for all the models
class RecServ(models.Model):
allocationid = models.AutoField(db_column='AllocationID', primary_key=True) # Field name made lowercase.
servrecid = models.ForeignKey('Service', models.DO_NOTHING, db_column='ServRecID') # Field name made lowercase.
receiptno = models.ForeignKey(Receipt, models.DO_NOTHING, db_column='ReceiptNo') # Field name made lowercase.
(关系比我在上面的片段中显示的要多)
有了这个,我现在可以进行如下查询:
q = models.Service.objects.select_related('visitrecordid__servdoctor').select_related('visitrecordid__invoiceto') \
.select_related('visitrecordid__patientno').select_related('itemno').select_related(
'servrecid_1__receiptno').all()[:5]
它使用这些连接创建一个查询:
... FROM [SERVICE] INNER JOIN [REC_SERV] ON ([SERVICE].[ServRecID] = [REC_SERV].[ServRecID])
INNER JOIN [RECEIPT] ON ([REC_SERV].[ReceiptNo] = [RECEIPT].[ReceiptNo])
LEFT OUTER JOIN [VISIT] ON ([SERVICE].[VisitRecordID] = [VISIT].[VisitRecordID])
LEFT OUTER JOIN [CM_PATIENT] ON ([VISIT].[PatientNo] = [CM_PATIENT].[PATIENT_ID])
LEFT OUTER JOIN [DOCTOR] ON ([VISIT].[ServDoctor] = [DOCTOR].[DoctorCode])
LEFT OUTER JOIN [INVOICETO] ON ([VISIT].[InvoiceTo] = [INVOICETO].[InvoiceTo])
INNER JOIN [FEES] ON ([SERVICE].[ItemNo] = [FEES].[ItemNo])
第一次加入只是因为我的 FK 错误而出现。 SQL 对我来说看起来很好,我想我已经解决了我的问题。
这实际上应该有效吗?两个表之间的相互外键关系现在会发生什么?