英文:
How to use DEFAULT when inserting rows into postgres sql database
问题
考虑到我在我的PostgreSQL数据库中有一个名为t1的表,如下所示:
CREATE TABLE t1 (
id SERIAL PRIMARY KEY,
col_2 TEXT DEFAULT "foo",
col_3 TEXT NOT NULL DEFAULT "bar",
...
col_X INTEGER NOT NULL DEFAULT 42
);
并且我收到一个JSON对象obj
,我将其解组为一个结构体ObjStrct
:
type ObjStrct {
id *int32 `json:id,omitempty`,
s1 *string `json:s1,omitempty`,
s2 *string `json:s2,omitempty`,
...
nr *int32 `json:nr,omitempty`
}
var obj ObjStrct
err := json.NewDecoder(request.Body).Decode(&obj)
// 错误处理已完成
现在我想将该对象插入到我的数据库中:
// 连接到数据库已建立
row := db.QueryRow(
`INSERT INTO
t1 (col_1, col_2, ..., col_X)
VALUES
($1, $2, ..., $X)
RETURNING
id;`,
*obj.s1, *obj.s2, ..., *obj.nr)
问题是:所有这些obj.*
值都可以为nil
,在这种情况下应该使用SQL的DEFAULT值。
我的问题是:我该如何实现这一点?
-
来自sql包的数据类型(sql.Null
)据我所知不支持DEFAULT关键字。 -
像
func defaultOnNil(v *int32) any { ... }
这样的函数,当v
为nil时返回"DEFAULT",而不是v
,是不起作用的。请参阅此相关帖子。
英文:
Consider that I have a table t1 in my postgres database like so:
CREATE TABLE t1 (
id SERIAL PRIMARY KEY,
col_2 TEXT DEFAULT "foo",
col_3 TEXT NOT NULL DEFAULT "bar",
...
col_X INTEGER NOT NULL DEFAULT 42
);
And that I receive a JSON object obj
which I unmarshall in a struct ObjStrct
:
type ObjStrct {
id *int32 `json:id,omitempty`,
s1 *string `json:s1,omitempty`,
s2 *string `json:s2,omitempty`,
...
nr *int32 `json:nr,omitempty`
}
var obj ObjStrct
err := json.NewDecoder(request.Body).Decode(&obj)
// error handling has been done
Now I want to insert that object into my database:
// connection to db established
row := db.QueryRow(
`INSERT INTO
t1 (col_1, col_2, ..., col_X)
VALUES
($1, $2, ..., $X)
RETURNING
id;`,
*obj.s1, *obj.s2, ..., *obj.nr)
The issue is: All those obj.*
-values could be nil
in which case the sql DEFAULT value should be used.
My question is: How do I achieve this?
-
datatypes from the sql package (sql.Null<TYPE>) do not support the DEFAULT keyword afaik.
-
Functions like
func defaultOnNil(v *int32) any { ... }
returning "DEFAULT" whenv
is nil andv
instead do not work. See this related post
答案1
得分: 2
使用列的DEFAULT
值时,INSERT
应该在插入时排除该列。
这意味着你需要处理JSON对象,找出哪些值为nil,并从查询中删除它们。
例如,如果JSON对象的s2
为nil,则应该从查询中删除col2
;它应该修改为:
row := db.QueryRow(
`INSERT INTO
t1 (col_1, ..., col_X) -- 这里删除了"col2"
VALUES
($1, ..., $X) -- 这里删除了"$2"
RETURNING
id, col2;`, -- 这里添加了"col2"
*obj.s1, *obj.s2)
任何实现动态SQL功能的ORM都可以轻松完成这个操作。
英文:
To use the DEFAULT
value of a column an INSERT
should exclude the column while inserting.
This means, you'll need to process the JSON object, find out which values are nil, and remove them from the query.
For example, if the JSON object has s2
as nil, then col2
should be removed from your query; it should be modified as:
row := db.QueryRow(
`INSERT INTO
t1 (col_1, ..., col_X) -- "col2" removed here
VALUES
($1, ..., $X) -- "$2" removed here
RETURNING
id, col2;`, -- "col2" added here
*obj.s1, *obj.s2)
This is easily done by any ORM that implements Dynamic SQL functionality.
答案2
得分: 0
另一个选项是在json解析的值之前发送关键字DEFAULT。所以代码如下:
row := db.QueryRow(
`INSERT INTO
t1 (col_1, col_2, ..., col_X)
VALUES
($1, $2, ..., $X)
RETURNING
id;`,
*obj.s1, DEFAULT, ..., *obj.nr);
在这种用法中,不需要在DEFAULT周围使用引号,因为它是一个关键字。
英文:
Another option is send the keyword DEFAULT instead of the value parsed from the json. So:
row := db.QueryRow(
`INSERT INTO
t1 (col_1, col_2, ..., col_X)
VALUES
($1, $2, ..., $X)
RETURNING
id;`,
*obj.s1, DEFAULT, ..., *obj.nr);
You do not use quotes around DEFAULT, in this usage it is a keyword.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论