Django 相当于 SQL REPLACE

发布于 2024-09-18 15:47:40 字数 630 浏览 4 评论 0原文

是否有针对此 SQL 的 Django ORM 最佳实践:

REPLACE app_model SET field_1 = 'some val', field_2 = 'some val';

假设:field_1 或 field_2 将有一个唯一的键(或者在我的情况下两者都有),否则这将始终评估为 INSERT。

编辑:

我现在最好的个人答案是这样的,但它是 2-3 个查询,其中 1 个应该是可能的:

    from django.core.exceptions import ValidationError
    try:
        Model(field_1='some val',field_2='some val').validate_unique()
        Model(field_1='some val',field_2='some val',extra_field='some val').save()
    except ValidationError:
        Model.objects.filter(field_1='some val',field_2='some val').update(extra_field='some val')

Is there a Django ORM best practice for this SQL:

REPLACE app_model SET field_1 = 'some val', field_2 = 'some val';

Assumption: field_1 or field_2 would have a unique key on them (or in my case on both), otherwise this would always evaluate to an INSERT.

Edit:

My best personal answer right now is this, but it's 2-3 queries where 1 should be possible:

    from django.core.exceptions import ValidationError
    try:
        Model(field_1='some val',field_2='some val').validate_unique()
        Model(field_1='some val',field_2='some val',extra_field='some val').save()
    except ValidationError:
        Model.objects.filter(field_1='some val',field_2='some val').update(extra_field='some val')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

2024-09-25 15:47:40

您说您想要 REPLACE ,我相信这应该在插入之前删除任何现有行,但您的示例表明您想要更像 UPSERT

AFAIK,django 不支持 REPLACE (或 sqlite 的 INSERT OR REPLACEUPSERT)。但是您的代码可以合并:

obj, created = Model.objects.get_or_create(field_1='some val', field_2='some_val')
obj.extra_field = 'some_val'
obj.save()

这当然假设 field_1field_2 或两者都是唯一的(正如您所说)。

它仍然是两个查询(用于 get_or_createSELECT 和用于 saveINSERT 或 UPDATE code>),但在类似 UPSERT 的解决方案出现之前(而且可能不会持续很长一段时间),这可能是您能做的最好的事情。

You say you want REPLACE, which I believe is supposed to delete any existing rows before inserting, but your example indicates you want something more like UPSERT.

AFAIK, django doesn't support REPLACE (or sqlite's INSERT OR REPLACE, or UPSERT). But your code could be consolidated:

obj, created = Model.objects.get_or_create(field_1='some val', field_2='some_val')
obj.extra_field = 'some_val'
obj.save()

This of course assumes that either field_1, field_2, or both are unique (as you've said).

It's still two queries (a SELECT for get_or_create, and an INSERT or UPDATE for save), but until an UPSERT-like solution comes along (and it may not for a long, long time), it may be the best you can do.

奢望 2024-09-25 15:47:40

从 Django 1.7 开始,您可以使用 update_or_create< /code>方法:

obj, created = Person.objects.update_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'profession': 'musician'},
)

Since Django 1.7 you can use update_or_create method:

obj, created = Person.objects.update_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'profession': 'musician'},
)
守望孤独 2024-09-25 15:47:40

我认为下面的方法更有效。

(obj, created) = Model.objects.get_or_create(
   field_1 = 'some val',
   field_2 = 'some_val',
   defaults = {
      'extra_field': 'some_val'
   },
)
if not created and obj.extra_field != 'some_val':
   obj.extra_field = 'some_val'
   obj.save(
      update_fields = [
         'extra_field',
      ],
   )

如果该行尚未创建且需要更新,这只会更新 extra_field。

I think the following is more efficient.

(obj, created) = Model.objects.get_or_create(
   field_1 = 'some val',
   field_2 = 'some_val',
   defaults = {
      'extra_field': 'some_val'
   },
)
if not created and obj.extra_field != 'some_val':
   obj.extra_field = 'some_val'
   obj.save(
      update_fields = [
         'extra_field',
      ],
   )

This will only update the extra_field if the row was not created and needs to be updated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文