为了账号安全,请及时绑定邮箱和手机立即绑定

使用 pgx 和 go 在简单的 postgresql 查询中返回 id

使用 pgx 和 go 在简单的 postgresql 查询中返回 id

Go
哈士奇WWW 2022-11-08 16:59:06
我正在尝试运行这个简单的查询来返回 id,根据作者的说法,我们使用 QueryRow 函数,好的,但是这个查询结果返回了一个期望 2 个 args 但在这里某处收到 3 个错误。查询模型.go type WidgetetModel struct {    DB *pgxpool.Pool}func (m *WidgetModel) Insert(title, content, expires string) (int, error) {        stmt := `INSERT INTO widgets (title, content, created, expires) VALUES($1, $2, NOW(), NOW() + INTERVAL '$3 day') RETURNING id;`            var id int        err := m.DB.QueryRow(context.Background(), stmt, title, content, expires).Scan(&id)        if err != nil {            if errors.Is(err, sql.ErrNoRows) {                return 0, models.ErrNoRecord            } else {                return 0, err            }        }            return 0, nil    }处理程序.gofunc (app *application) createWidget(w http.ResponseWriter, r *http.Request) {    if r.Method != http.MethodPost {        w.Header().Set("Allow", http.MethodPost)        app.clientError(w, http.StatusMethodNotAllowed) // Use the clientError() helper.        return    }    title := "Widget 1"    content := "Some content here..."    expires := "7"    id, err := app.widgets.Insert(title, content, expires)    if err != nil {        app.serverError(w, err) <-- line 57        return    }    http.Redirect(w, r, fmt.Sprintf("/widget?id=%v", id), http.StatusSeeOther)}main.go我只是在这里使用一个结构来为我的处理程序注入依赖项。dbPool, err := openDB(*dsn)    if err != nil {        errorLog.Fatal(err)    }    defer dbPool.Close()app := &application{        errorLog: errorLog,        infoLog:  infoLog,        snippets: &postgresql.WidgetModel{DB: dbPool},}///func openDB(dsn string) (*pgxpool.Pool, error) {    pool, err := pgxpool.Connect(context.Background(), dsn)    if err != nil {        return nil, err    }    if err = pool.Ping(context.Background()); err != nil {        return nil, err    }    return pool, nil}
查看完整描述

2 回答

?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

从您收到的错误中:

expected 2 arguments, got 3

我怀疑$3在 SQL 引号内的查询中不会被解释为参数。另外据我所知,这不是在 postgres 中使用参数间隔的正确方法。正确的方法是写interval '1 day' * $1

所以我认为如果您将代码更改为:

stmt := `INSERT INTO widgets (title, content, created, expires) VALUES($1, $2, NOW(), NOW() + INTERVAL '1 day' * $3) RETURNING id;`

它会起作用的。但请确保将expires参数更改为 int 类型。


查看完整回答
反对 回复 2022-11-08
?
当年话下

TA贡献1890条经验 获得超9个赞

'$3 day' 您不能将查询参数作为字符串文字的一部分传递。


尝试将所有INTERVAL '$3 day'部分替换为参数。像这个。


func (m *WidgetModel) Insert(title, content, expires string) (int, error) {

    stmt := `

INSERT INTO widgets (title, content, created, expires)

VALUES ($1, $2, NOW(), NOW() + $3)

RETURNING id;`


    var id int

    expiresDays, err := strconv.ParseInt(expires, 10, 32)

    if err != nil {

        return 0, err

    }

    expiresInterval := pgtype.Interval{

        Days:   int32(expiresDays),

        Status: pgtype.Present}

    err = m.DB.QueryRow(context.Background(), stmt, title, content,

        expiresInterval).Scan(&id)

    if err != nil {

        if errors.Is(err, sql.ErrNoRows) {

            return 0, models.ErrNoRecord

        } else {

            return 0, err

        }

    }


    return 0, nil

}


查看完整回答
反对 回复 2022-11-08
  • 2 回答
  • 0 关注
  • 174 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号