第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

如何使用 `database/sql` 實(shí)現(xiàn) PATCH?

如何使用 `database/sql` 實(shí)現(xiàn) PATCH?

Go
www說(shuō) 2022-10-17 19:31:08
假設(shè)您有一個(gè)由 SQL 數(shù)據(jù)庫(kù)支持的基本 API (GET/POST/PATCH/DELETE)。PATCH 調(diào)用應(yīng)該只更新用戶(hù)發(fā)送的 JSON 有效負(fù)載中的字段,而不涉及任何其他字段。想象一下表(我們稱(chēng)它為sample)有id,string_a和string_b列,與之對(duì)應(yīng)的結(jié)構(gòu)如下所示:type Sample struct {  ID      int    `json:"id"`  StringA string `json:"stringA"`  StringB string `json:"stringB"`}假設(shè)用戶(hù){ "stringA": "patched value" }作為有效負(fù)載傳入。json 將被解組為如下所示的內(nèi)容:&Sample{ ID: 0, StringA: "patched value", StringB: "",}對(duì)于使用 的項(xiàng)目database/sql,您將編寫(xiě)查詢(xún)來(lái)修補(bǔ)行,例如:// `id` is from the URL paramsquery := `UPDATE sample SET string_a=$1, string_b=$2 WHERE id=$3`row := db.QueryRow(query, sample.StringA, sample.StringB, id)...該查詢(xún)將按string_a預(yù)期更新該列,但它也會(huì)將該string_b列更新為"",在這種情況下這是不希望的行為。本質(zhì)上,我只是創(chuàng)建了一個(gè) PUT 而不是 PATCH。我的直接想法是——好的,沒(méi)關(guān)系,讓我們用它strings.Builder來(lái)構(gòu)建查詢(xún),只為那些具有非 nil/空值的語(yǔ)句添加一個(gè) SET 語(yǔ)句。但是,在那種情況下,如果用戶(hù)想要string_a清空,他們將如何實(shí)現(xiàn)呢?例如。用戶(hù)使用有效負(fù)載進(jìn)行 PATCH 調(diào)用{ "stringA": "" } 。這將被解組為:&Sample{  ID: 0,  StringA: "",  StringB: "",}我理論化的“查詢(xún)構(gòu)建器”會(huì)看著它并說(shuō)“好的,這些都是 nil/空值,不要將它們添加到查詢(xún)中”并且不會(huì)更新任何列,這又是不受歡迎的行為。我不確定如何編寫(xiě)我的 API 以及它以同時(shí)滿(mǎn)足這兩種情況的方式運(yùn)行的 SQL 查詢(xún)。有什么想法嗎?
查看完整描述

2 回答

?
慕斯709654

TA貢獻(xiàn)1840條經(jīng)驗(yàn) 獲得超5個(gè)贊

我認(rèn)為較小查詢(xún)的合理解決方案是動(dòng)態(tài)構(gòu)建UPDATE查詢(xún)和綁定參數(shù)列表,同時(shí)使用識(shí)別更新內(nèi)容和留空內(nèi)容的邏輯處理有效負(fù)載。


根據(jù)我自己的經(jīng)驗(yàn),這是清晰易讀的(如果重復(fù),您始終可以迭代共享相同邏輯或使用反射并查看結(jié)構(gòu)標(biāo)記提示等的結(jié)構(gòu)成員)。每次(我)為此編寫(xiě)通用解決方案的嘗試都以非常復(fù)雜的矯枉過(guò)正,支持各種極端情況和端點(diǎn)之間的行為差異。


func patchSample(s Sample) {

    var query strings.Builder

    params := make([]interface{}, 0, 2)


    // TODO Check if patch makes sense (e.g. id is non-zero, at least one patched value provided, etc.


    query.WriteString("UPDATE sample SET")


    if s.StringA != "" {

        query.WriteString(" stringA = ?")

        params = append(params, s.StringA)

    }


    if s.StringB != "" {

        query.WriteString(" stringB = ?")

        params = append(params, s.StringB)

    }


    query.WriteString(" WHERE id = ?")

    params = append(params, s.ID)


    fmt.Println(query.String(), params)

    //_, err := db.Exec(query.String(), params...)

}


func main() {

    patchSample(Sample{1, "Foo", ""})

    patchSample(Sample{2, "", "Bar"})

    patchSample(Sample{3, "Foo", "Bar"})

}

編輯:如果""是修補(bǔ)的有效值,那么它需要與默認(rèn)的空值區(qū)分開(kāi)來(lái)。解決字符串問(wèn)題的一種方法是使用指針,nil如果有效載荷中不存在值,則默認(rèn)為:


type Sample struct {

    ID      int     `json:"id"`

    StringA *string `json:"stringA"`

    StringB *string `json:"stringB"`

}

然后修改條件以檢查字段是否像這樣發(fā)送:


if s.StringA != nil {

    query.WriteString(" stringA = ?")

    params = append(params, *s.StringA)

}

在操場(chǎng)上查看完整示例:https ://go.dev/play/p/RI7OsNEYrk6


查看完整回答
反對(duì) 回復(fù) 2022-10-17
?
婷婷同學(xué)_

TA貢獻(xiàn)1844條經(jīng)驗(yàn) 獲得超8個(gè)贊

對(duì)于它的價(jià)值,我通過(guò)以下方式解決了這個(gè)問(wèn)題:

  1. 將請(qǐng)求有效負(fù)載轉(zhuǎn)換為通用map[string]interface{}.

  2. 實(shí)現(xiàn)一個(gè)查詢(xún)構(gòu)建器,該構(gòu)建器循環(huán)遍歷地圖的鍵以創(chuàng)建查詢(xún)。

我走這條路的部分原因是它符合我的所有要求,而且我不是特別喜歡有*strings 或*ints 躺在那里。

以下是查詢(xún)構(gòu)建器的樣子:

func patchQueryBuilder(id string, patch map[string]interface{}) (string, []interface{}, error) {

    var query strings.Builder

    params := make([]interface{}, 0)


    query.WriteString("UPDATE some_table SET")

    for k, v := range patch {

        switch k {

        case "someString":

            if someString, ok := v.(string); ok {

                query.WriteString(fmt.Sprintf(" some_string=$%d,", len(params)+1))

                params = append(params, someString)

            } else {

                return "", []interface{}{}, fmt.Errorf("could not process some_string")

            }

        case "someBool":

            if someBool, ok := v.(bool); ok {

                query.WriteString(fmt.Sprintf(" some_bool=$%d,", len(params)+1))

                params = append(params, someBool)

            } else {

                return "", []interface{}{}, fmt.Errorf("could not process some_bool")

            }

        }

    }


    if len(params) > 0 {

        // Remove trailing comma to avoid syntax errors

        queryString := fmt.Sprintf("%s WHERE id=$%d RETURNING *", strings.TrimSuffix(query.String(), ","), len(params)+1)

        params = append(params, id)

        return queryString, params, nil

    } else {

        return "", []interface{}{}, nil

    }

}

請(qǐng)注意,我使用的是 PostgreSQL,所以我需要為查詢(xún)提供編號(hào)參數(shù),例如$1,這是params用于的。它也是從函數(shù)返回的,因此可以按如下方式使用:


// Build the patch query based on the payload

query, params, err := patchQueryBuilder(id, patch)

if err != nil {

    return nil, err

}


// Use the query/params and get output

row := tx.QueryRowContext(ctx, query, params...)


查看完整回答
反對(duì) 回復(fù) 2022-10-17
  • 2 回答
  • 0 關(guān)注
  • 143 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)