【问题标题】:Update record in table with array value用数组值更新表中的记录
【发布时间】:2021-02-18 11:50:30
【问题描述】:

我正在尝试使用值数组(切片)更新 postgres 表中的记录。该表具有以下 DDL:

CREATE TABLE slm_files (
    id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
    filename character varying NOT NULL,
    status character varying NOT NULL,
    original_headers text[]
);

我的Go代码如下:

package main

import (
    "context"
    "database/sql"
    "encoding/json"
    "fmt"
    "os"
    "strings"
    "time"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/lib/pq"
)

type message struct {
    ID              string   `json:"id"`
    Filename        string   `json:"filename"`
    Status          string   `json:"status"`
    OriginalHeaders []string `json:"OriginalHeaders"`
}

func main() {
    host := os.Getenv("PGhost")
    port := 5432
    user := os.Getenv("PGuser")
    password := os.Getenv("PGpassword")
    dbname := os.Getenv("PGdbname")

    pgConString := fmt.Sprintf("port=%d host=%s user=%s "+
        "password=%s dbname=%s sslmode=disable",
        port, host, user, password, dbname)

    msgBody := `update_headers___
  {
      "id": "76b67119-d8c1-4a20-b53e-49e4972e2f19",
      "filename": "SLM1171_inputData_preNCOA-5babc88b-1d14-468d-bf6e-c3b36ce90d95.csv",
      "status": "Submitted",
      "OriginalHeaders": [
          "city",
          "state",
          "zipcode",
          "full_name",
          "individual_id"
      ]
  }`
    fmt.Println("Processing file", msgBody)
    queryMethod := strings.Split(msgBody, "___")[0]
    fieldDict := strings.Split(msgBody, "___")[1]

    db, err := sql.Open("postgres", pgConString)
    if err != nil {
        panic(err)
    }
    fmt.Println("Connected Successfully")
    defer db.Close()

    body := message{}
    json.Unmarshal([]byte(fieldDict), &body)
    fmt.Println(queryMethod)
    fmt.Println(body)

    var sqlStatement string
    switch queryMethod {
    case "update_ncoa":
        sqlStatement = fmt.Sprintf(`UPDATE slm_files SET status = '%s', updated_at = '%s' where id = '%s';`,
            body.Status,
            body.UpdatedAt,
            body.ID,
        )
    case "update_headers":
        sqlStatement = fmt.Sprintf(`UPDATE slm_files SET original_headers = '%s', updated_at = '%s' where id = '%s';`,
            pq.Array(body.OriginalHeaders),
            body.UpdatedAt,
            body.ID,
        )
    }
    fmt.Println(sqlStatement)
    _, err = db.Query(sqlStatement)
    if err != nil {
        fmt.Println("Failed to run query", err)
        return
    }
}
    fmt.Println("Query executed!")
    return
}

但我不断收到错误

pq: malformed array literal: "&[first_name last_name city state zipcode full_name individual_id]": Error
null

我在互联网上阅读了一些内容,导致我使用pq.Array(),但这似乎不起作用。

我已经阅读了 Go 数组和 Postgres 数组在格式上的区别,所以我希望让 pq.Array 函数能够解决它,但显然不是。

【问题讨论】:

  • 不要使用 Sprintf 来构造 SQL 查询,至少对于动态值不是。这为 SQL 注入打开了大门。改为使用占位符和 Exec 的可变参数,如 the docs 所示。
  • 谢谢,我知道这不是最佳实践,但这是不属于我的遗留代码,我只需要做这件事
  • 这不仅仅是最佳实践,它也关乎正确性。 Sprintf 不会产生有效的 SQL 语法,所以它不会工作。你必须重写代码。

标签: postgresql go


【解决方案1】:

正如彼得建议的那样,数据库处理有很多问题需要解决。并且绝对值得重做那些 SQL 语句以不使用 Sprintf 进行查询。

但就仅使用 postgres 数组和 pq 库而言,您需要使用 pq.Array 的 Value() 方法来获取 postgres 格式。将标题的更新语句更改为如下内容:

arrayVal, _ := pq.Array(body.OriginalHeaders).Value()
sqlStatement = fmt.Sprintf(`UPDATE slm_files SET original_headers = '%s', updated_at = '%s' where id = '%s';`,
        arrayVal,
        body.UpdatedAt,
        body.ID,
    )

值得检查 Value() 方法的返回以确保没有错误,我只是为了一个简单的示例而忽略了它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多