亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 golang 應用程序中創建具有多個 JSON 參數的 SQL 查詢?

如何在 golang 應用程序中創建具有多個 JSON 參數的 SQL 查詢?

Go
慕的地8271018 2022-04-26 10:47:07
正如您在我的Golang應用程序中看到的那樣,我有一個名為layers.type Details struct {    Total int `json:"total"`    Gender string `json:"gender"`}type Layer struct {    ID int `json:"id"`    City string `json:"city"`    Details []Details `json:"details"`}layers := []Layer{    {        ID: 107509018555,        City: "London",        Details: []Details{            {                Total: 158,                Gender: "Male",            },            {                Total: 689,                Gender: "Female",            },        },    },    {        ID: 108509018556,        City: "New York",        Details: []Details{            {                Total: 756,                Gender: "Male",            },            {                Total: 356,                Gender: "Female",            },        },    },}我想將該數組的數據插入到PostgreSQL數據庫的表中。我的問題是如何在應用程序中創建這樣的 SQL 查詢?查詢:INSERT INTO layers (ID, CITY, DETAILS) VALUES(107509018555, 'London', '[{"total":158,"gender":"Male"},{"total":689,"gender":"Female"}]'::json),(108509018556, 'New York', '[{"total":756,"gender":"Male"},{"total":356,"gender":"Female"}]':json);
查看完整描述

1 回答

?
白衣染霜花

TA貢獻1796條經驗 獲得超10個贊

因為我無法發表評論,所以我假設:

  1. 您正在使用 golang 的database/sql或類似的包。

  2. 在您的數據庫中,details列具有類型JSONB

一種簡單的方法是循環切片layers并為此構建查詢字符串:

"INSERT INTO layers (id,city,details) VALUES ($1,$2,$3), ($4,$5,$6)"

對于idcity,您可以輕松傳遞參數,但是您需要為 傳遞 JSON 字節details。這意味著,您需要將詳細信息結構編組為 JSON 字節以進行插入/更新,并在 SELECT 時將“詳細信息”結果解組為結構

您將需要:

  1. 定義封裝切片的新結構Detail(我們稱之為Details)然后Details應該實現這些接口。

  2. 實現driver.Valuer接口轉換Details為數據庫可以理解的JSON字節切片

  3. 實現sql.Scanner接口以將 JSON 字節切片從數據庫解組到您的結構

代碼應如下所示:

type Detail struct {

    Total  int    `json:"total"`

    Gender string `json:"gender"`

}


// this will implement driver.Valuer and sql.Scanner

type Details []Detail


// so that the database can understand your value, useful for INSERT/UPDATE

func (d Details) Value() (driver.Value, error) {

    return json.Marshal(d)

}


// so that the database can convert db value to your struct, useful for SELECT

func (d *Details) Scan(value interface{}) error {

    b, ok := value.([]byte)

    if !ok {

        return errors.New("type assertion to []byte failed for scanning Details")

    }


    return json.Unmarshal(b, &d)

}

完整代碼:


package main


import (

    "database/sql"

    "database/sql/driver"

    "encoding/json"

    "errors"

    "fmt"

    "log"

    "strings"


    _ "github.com/lib/pq"

)


type Layer struct {

    ID      int     `json:"id"`

    City    string  `json:"city"`

    Details Details `json:"details"`

}


// this will implement driver.Valuer and sql.Scanner

type Details []Detail


// so that the database can understand your value, useful for INSERT/UPDATE

func (d Details) Value() (driver.Value, error) {

    return json.Marshal(d)

}


// so that the database can convert db value to your struct, useful for SELECT

func (d *Details) Scan(value interface{}) error {

    b, ok := value.([]byte)

    if !ok {

        return errors.New("type assertion to []byte failed for scanning Details")

    }


    return json.Unmarshal(b, &d)

}


type Detail struct {

    Total  int    `json:"total"`

    Gender string `json:"gender"`

}


func main() {

    db, err := sql.Open("postgres", "postgres://user:pass@host:port/db?sslmode=disable")

    exitIfError(err)


    query, params := prepareQuery([]Layer{

        {

            ID:      107509018555,

            City:    "London",

            Details: []Detail{{Total: 158, Gender: "Male"}, {Total: 689, Gender: "Female"}},

        },

        {

            ID:      108509018556,

            City:    "New York",

            Details: []Detail{{Total: 756, Gender: "Male"}, {Total: 356, Gender: "Female"}},

        },

    })


    log.Println(query) 

    // INSERT INTO layers (id, city, details) VALUES ($1, $2, $3),($4, $5, $6)

    log.Println(params) 

    // [107509018555 London [{158 Male} {689 Female}] 108509018556 New York [{756 Male} {356 Female}]]


    result, err := db.Exec(query, params...)

    exitIfError(err)



    rows, _ := result.RowsAffected()

    log.Println(rows) // 2 rows inserted

}


func exitIfError(err error) {

    if err != nil {

        log.Fatal(err)

    }

}


func prepareQuery(layers []Layer) (string, []interface{}) {

    query := "INSERT INTO layers (id, city, details) VALUES "

    params := []interface{}{}

    x := 1


    for _, layer := range layers {

        query += fmt.Sprintf("($%d, $%d, $%d),", x, x+1, x+2)

        params = append(params, layer.ID, layer.City, layer.Details)

        x += 3

    }


    query = strings.TrimSuffix(query, ",")

    return query, params

}



查看完整回答
反對 回復 2022-04-26
  • 1 回答
  • 0 關注
  • 216 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號