Go语言 如何在postgres sql数据库中插入行时使用DEFAULT

nvbavucw  于 2023-06-19  发布在  Go
关注(0)|答案(2)|浏览(151)

假设我在postgres数据库中有一个表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)
// error handling has been done

现在我想把这个对象插入到我的数据库中:

// 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)

问题是:所有这些obj.*-值都可以是nil,在这种情况下,应该使用sql DEFAULT值。
我的问题是:我如何做到这一点?

  • sql包(sql.Null)中的数据类型不支持DEFAULT关键字afaik。
  • func defaultOnNil(v *int32) any { ... }这样的函数在v为nil时返回“DEFAULT”,而v则不起作用。参见this related post
s5a0g9ez

s5a0g9ez1#

要使用DEFAULT列的值,INSERT在插入时应该排除该列
这意味着,您需要处理JSON对象,找出哪些值是nil,并将它们从查询中删除。
例如,如果JSON对象的s2为nil,则应该从查询中删除col2;应修改为:

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)

任何实现了动态SQL功能的ORM都可以轻松地做到这一点。

e3bfsja2

e3bfsja22#

另一个选项是发送关键字DEFAULT,而不是从json解析的值。所以:

row := db.QueryRow(
        `INSERT INTO 
            t1 (col_1, col_2, ..., col_X)
        VALUES
            ($1, $2, ..., $X)
        RETURNING 
            id;`, 
        *obj.s1, DEFAULT, ..., *obj.nr);

在DEFAULT前后不要使用引号,在这种用法中,它是一个关键字。

相关问题