golang中使用gorm进行upsert操作并返回结果。

huangapple go评论85阅读模式
英文:

golang gorm upsert with returning

问题

在我的golang项目中,我使用gorm,并且我需要使用返回子句进行upsert查询,以获取查询中修改后的值。我可以进行upsert操作,但是我无法弄清楚如何将返回子句与其连接起来。表名为counters,代码如下:

te := struct {
    Name    string //key column
    Counter int
}{
    Name:    "name_to_update",
    Counter: 2,
}

DB.
    //Model(te).
    Clauses(
        //clause.Returning{Columns: []clause.Column{{Name: "counter"}}},
        clause.OnConflict{
            Columns: []clause.Column{{Name: "name"}}, // key column
            DoUpdates: clause.Assignments(map[string]interface{}{
                "counter": gorm.Expr("counters.counter + ?", 1),
            }),
        },
    ).Create(&te)

生成的SQL查询语句如下:

INSERT INTO "counters" ("counter", "name") VALUES (0, "name_to_update") ON CONFLICT ("name") 
DO UPDATE SET "counter"=counters.counter + 1 RETURNING "name" --我需要更新后的counter值,而不是name

所以计数器已经更新,这是没问题的,但是它返回给我键列(在RETURNING中),而我需要计数器的更新值。有什么办法可以解决吗?谢谢
英文:

In my golang project I use gorm and I need to make upsert query with returning clause to get the modified value from the query. I can make upsert, but I cannot figure out how to connect the returnning clause to it. The table name is counters, the code is as follows:

te := struct {
		Name string //key column
		Counter int
	}{
		Name: "name_to_update",
		Counter: 2,
	}

DB.
	//Model(te).
	Clauses(
		//clause.Returning{Columns: []clause.Column{{Name: "counter"}}},
		clause.OnConflict{
			Columns: []clause.Column{{Name: "name"}}, // key column
			DoUpdates: clause.Assignments(map[string]interface{}{
				"counter": gorm.Expr("counters.counter + ?", 1),
			}),
		},
	).Create(&te)

The resulting SQL query is:

INSERT INTO "counters" ("counter", "name") VALUES (0, "name_to_update") ON CONFLICT ("name") 
DO UPDATE SET "counter"=counters.counter + 1 RETURNING "name" //I need updated counter value here, not name  

So the counter is updated and this is OK, but it returns me the key column (in RETURNING) while I need the updated value of the counter. Any ideas how to fix it? Thank you

答案1

得分: 2

我不确定匿名结构体是否会引发问题。

此外,从你的代码中无法确定表名 "counters" 是从哪里获取的。

我尝试了你的解决方案 - 使用一个专门的结构体来表示模型 - 并且它完全正常工作。

type Counter struct {
    Name    string `gorm:"primaryKey"`
    Counter int
}

...

counter := Counter{Name: "name_to_update", Counter: 2}

db.
    Clauses(
        clause.Returning{Columns: []clause.Column{{Name: "counter"}}},
        clause.OnConflict{
            Columns: []clause.Column{{Name: "name"}},
            DoUpdates: clause.Assignments(map[string]interface{}{
                "counter": gorm.Expr("counters.counter + ?", 1),
            }),
        },
    ).Create(&counter)

fmt.Println(counter.Counter)

上述代码生成以下 SQL 语句:

INSERT INTO "counters" ("name","counter") VALUES ('name_to_update',10) ON CONFLICT ("name") DO UPDATE SET "counter"=counters.counter + 1 RETURNING "counter"

counter.Counter 的值已经正确更新。

英文:

I'm not sure if the anonymous struct causes an issue.

Also, it's unclear from your code where the table name - "counters" - comes from.

I've tried your solution - but with a dedicated struct for the model - and it works just fine.

type Counter struct {
	Name    string `gorm:"primaryKey"`
	Counter int
}

...

counter := Counter{Name: "name_to_update", Counter: 2}

	db.
		Clauses(
			clause.Returning{Columns: []clause.Column{{Name: "counter"}}},
			clause.OnConflict{
				Columns: []clause.Column{{Name: "name"}},
				DoUpdates: clause.Assignments(map[string]interface{}{
					"counter": gorm.Expr("counters.counter + ?", 1),
				}),
			},
		).Create(&counter)

	fmt.Println(counter.Counter)

The code above generates the following SQL

INSERT INTO "counters" ("name","counter") VALUES ('name_to_update',10) ON CONFLICT ("name") DO UPDATE SET "counter"=counters.counter + 1 RETURNING "counter" 

And counter.Counter has correct updated value.

huangapple
  • 本文由 发表于 2022年12月29日 17:04:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/74949143.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定