4

http://jinzhu.me/gorm/advanced.html#sql-builderから、単一の WHERE IN を使用して複数の行を更新(?)し、スライスを単一に渡す?ことができるはずWHERE IN (?,?,?,?)です。

次のように jinzhu.me からの例: db.Exec("UPDATE orders SET shipped_at=? WHERE id IN (?)", time.Now, []int64{11,22,33}). これは、それが機能していることを示す gorm のテストの例です。https://github.com/jinzhu/gorm/blob/021d7b33143de37b743d1cf660974e9c8d3f80ea/main_test.go#L449

しかし、これは私にとってはうまくいきません:

var availableIds []int
for _, p := range v.Products {
    availableIds = append(availableIds, p.Id)
}

log.Println(availableIds)

db.Exec("UPDATE product_supplier SET deleted_at=? WHERE supplier_id = ? AND sku NOT IN (?)", time.Now(), 3, availableIds)

出力:

2016/04/19 07:48:44 [336 338 337 306 329 94 79 43 57 313 108 122 126 127 124 125 123 221 93 330 335 333 312]

(sql: expected 2 arguments, got 25)

ハードコーディングしようとすると、同じ問題が発生します。

db.Exec("UPDATE product_supplier SET deleted_at=? WHERE supplier_id = ? AND sku NOT IN (?)", time.Now(), 3, []int{313, 108})

出力:

(sql: expected 2 arguments, got 4)

解決:

コードは実際にはまったくバグがありません。私はばかげていましたか - 実際のコードに必要以上の余分なパラメーターがありました。スタックオーバーフローのために正しく翻訳しませんでした。私の悪い。

4

1 に答える 1

2

機能のprepare性質上、スライスを引数として渡すことはできません。

db.ExecGo での の実装では、最初prepareにクエリ (変数プレースホルダーを含む) を実行し、次に引数を送信します。

prepareスライスを渡せない理由が気になる場合は、この回答をお読みください。

回避策として、スライスのサイズと同じ量のプレースホルダーをプログラムで連結する必要があります。これにより、次のようなクエリが生成されます。

... WHERE supplier_id = ? AND sku NOT IN (?, ?, ?, ?)

コード例:

Ids := []int{1, 2, 3}
query := "... WHERE supplier_id = ? AND sku NOT IN (" + genVar(len(Ids)) + ")"
db.Exec(query, 3, Ids)

アップデート:

Gormのメソッドの実装では、DBMS の準備機能を使用していませんがdb.Exec、ドライバーで文字列を連結しています。

私の診断では、依存関係に何か問題がある可能性があります。

http://jinzhu.me/gorm/Gormに示されているようにインポートしていますか?

于 2016-04-19T09:52:48.817 に答える