Go语言 更新将忽略Limit子句

sd2nnvve  于 2022-12-07  发布在  Go
关注(0)|答案(1)|浏览(137)

Gorm似乎不支持在Update中使用Limit,也不抛出错误。

resUpdate := tx.Model(&daos.Voucher{}).
            Where("status = ?", models.VoucherStatusAvailable).
            Limit(quantity).
                        Scan(&vouchers).
            Update("status", models.VoucherStatusBooked)

此查询将更新我的数据库中的每个字段,从VoucherStatusAvailable到VoucherStatusBooked,而不考虑Limit的使用。
很快就有人提出了这个问题:https://penkovski.com/post/gorm-update-returning/但是他们将Limit放在Where子句中的解决方案:

resUpdate := tx.Model(&daos.Voucher{}).
            Where("status = ? LIMIT ?", models.VoucherStatusAvailable, quantity).
            Update("status", models.VoucherStatusBooked)

在使用gorm软删除时不起作用,因为它在where子句前后加上括号,并在其后加上AND deleted_at = NULL过滤器。
一开始我是用两个单独的查询(一个选择,然后一个更新)来做的,但是在这种情况下有冲突的可能。有人知道我应该如何选择表的X个成员,然后更新他们的状态,而不会有与所选项冲突的风险吗?
编辑:我使用的DBMS是PostgreSQL

ukxgm1gy

ukxgm1gy1#

不同点的人都回答道:

  1. Postgre不支持LIMIT和ORDER BY,所以我需要一个替代方案。
    1.正如评论中所指出的,正确的选择似乎是CTE。
  2. gorm支持自定义插件,且有一个实现CTE插件:https://github.com/WinterYukky/gorm-extra-clause-plugin。很遗憾,它与Update子句不兼容。
    1.因此,最终,我找到的唯一解决方案是在原始SQL中执行CTE:
var updated []Voucher
        resUpdate := tx.Raw(`WITH v AS (
            SELECT * from vouchers WHERE status = ?
            LIMIT ?
        )
        UPDATE vouchers SET status = ?
        WHERE EXISTS (SELECT * FROM v WHERE vouchers.id = v.id)
        RETURNING *`,
        models.ArticleStatusAvailable, quantity, models.VoucherStatusBooked).
        Scan(&updated)

相关问题