sql: 使用`preparex`和`context.context`预期8个参数,但实际得到了0个参数。

huangapple go评论111阅读模式
英文:

sql: expected 8 arguments, got 0 using `preparex` and `context.context`

问题

我的问题与那个问题无关。我的问题主要是关于preparexctx。我已经使用db.NamedExec完成了实现,我的代码对这些都有效。我在这里尝试做的是理解context.contextpreparex,并使用这两个进行实现。

代码片段:

model.go

  1. type User struct {
  2. ID int `db:"id" json:"id"`
  3. CreatedAt time.Time `db:"created_at" json:"created_at"`
  4. UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
  5. DeletedAt time.Time `db:"deleted_at" json:"deleted_at"`
  6. Username string `db:"username" json:"username"`
  7. Password string `db:"password" json:"password"`
  8. FirstName string `db:"first_name" json:"first_name"`
  9. LastName string `db:"last_name" json:"last_name"`
  10. Phone string `db:"phone" json:"phone"`
  11. Status bool `db:"status" json:"status"`
  12. Addrs []UserAddress
  13. }

查询:

  1. queryInsertUserData = `
  2. INSERT INTO users (id, created_at, updated_at, deleted_at, username, password, first_name, last_name, phone, status) VALUES($1, now(), now(), $2, $3, $4, $5, $6, $7, $8)
  3. `

  1. type queries struct {
  2. insertUserData,
  3. insertAddrData *sqlx.Stmt
  4. }
  5. // prepareStatement是一个用于准备sqlx语句的方法
  6. func (queries *queries) prepareStatement(db *sqlx.DB, query string) (*sqlx.Stmt, error) {
  7. stmt, err := db.Preparex(query) //https://go.dev/doc/database/prepared-statements
  8. if err != nil {
  9. return nil, err
  10. }
  11. return stmt, err
  12. }
  13. constructUserData, err := queries.prepareStatement(db, queryInsertUserData)
  14. queries.insertUserData = constructUserData

实现:

  1. // 插入用户数据
  2. func (postgres *Postgres) InsertUserData(ctx context.Context) (*entity.User, error) {
  3. c := entity.User{}
  4. err := postgres.queries.insertUserData.SelectContext(ctx, &c) //<---这里
  5. if err != nil {
  6. return nil, err
  7. }
  8. return &c, nil
  9. }

我的ctx是:

  1. ctx = context.WithValue(ctx, "ID", 1)
  2. ctx = context.WithValue(ctx, "Username", "John")
  3. ctx = context.WithValue(ctx, "Password", "pass")

当我传递给postgres.queries.insertUserData.SelectContext(ctx, &c)

我得到:sql: expected 8 arguments, got 0

为什么它说得到了0个参数?有人可以帮我解决这个问题吗?如何传递ctx并提供插入查询值?

英文:

My question is not related to that one. My question was mostly on preparex and ctx. I have already done with the implementation using the db.NamedExec and my code is working for those. What I am trying to do here is to understand context.context and preparex. Implement using these two.

CODE SNIPPET:

model.go

  1. type User struct {
  2. ID int `db:&quot;id&quot; json:&quot;id&quot;`
  3. CreatedAt time.Time `db:&quot;created_at&quot; json:&quot;created_at&quot;`
  4. UpdatedAt time.Time `db:&quot;updated_at&quot; json:&quot;updated_at&quot;`
  5. DeletedAt time.Time `db:&quot;deleted_at&quot; json:&quot;deleted_at&quot;`
  6. Username string `db:&quot;username&quot; json:&quot;username&quot;`
  7. Password string `db:&quot;password&quot; json:&quot;password&quot;`
  8. FirstName string `db:&quot;first_name&quot; json:&quot;first_name&quot;`
  9. LastName string `db:&quot;last_name&quot; json:&quot;last_name&quot;`
  10. Phone string `db:&quot;phone&quot; json:&quot;phone&quot;`
  11. Status bool `db:&quot;status&quot; json:&quot;status&quot;`
  12. Addrs []UserAddress
  13. }

Query:

  1. queryInsertUserData = `
  2. INSERT INTO users (id, created_at, updated_at, deleted_at, username, password, first_name, last_name, phone, status) VALUES($1, now(), now(), $2, $3, $4, $5, $6, $7, $8)
  3. `

  1. type queries struct {
  2. insertUserData,
  3. insertAddrData *sqlx.Stmt
  4. }
  5. //prepareStatement is a method for preparing sqlx statement
  6. func (queries *queries) prepareStatement(db *sqlx.DB, query string) (*sqlx.Stmt, error) {
  7. stmt, err := db.Preparex(query) //https://go.dev/doc/database/prepared-statements
  8. if err != nil {
  9. return nil, err
  10. }
  11. return stmt, err
  12. }
  13. constructUserData, err := queries.prepareStatement(db, queryInsertUserData)
  14. queries.insertUserData = constructUserData

Implementation:

  1. // Insert User data
  2. func (postgres *Postgres) InsertUserData(ctx context.Context) (*entity.User, error) {
  3. c := entity.User{}
  4. err := postgres.queries.insertUserData.SelectContext(ctx, &amp;c) //&lt;---here
  5. if err != nil {
  6. return nil, err
  7. }
  8. return &amp;c, nil
  9. }

my ctx is :

  1. ctx = context.WithValue(ctx, &quot;ID&quot;, 1)
  2. ctx = context.WithValue(ctx, &quot;Username&quot;, &quot;John&quot;)
  3. ctx = context.WithValue(ctx, &quot;Password&quot;, &quot;pass&quot;)

when I am passing to postgres.queries.insertUserData.SelectContext(ctx, &amp;c)

I am getting: sql: expected 8 arguments, got 0

why it is saying got 0? Can anyone help me with this? How to pass ctx and provide the insert query values?

答案1

得分: 1

我没有理解你的代码结构,但从主要的上下文(插入查询)来看,你应该像这样做:

  1. package main
  2. import (
  3. "context"
  4. "database/sql"
  5. "log"
  6. )
  7. var db *sql.DB
  8. type User struct {
  9. ID int `db:"id" json:"id"`
  10. CreatedAt time.Time `db:"created_at" json:"created_at"`
  11. UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
  12. DeletedAt time.Time `db:"deleted_at" json:"deleted_at"`
  13. Username string `db:"username" json:"username"`
  14. Password string `db:"password" json:"password"`
  15. FirstName string `db:"first_name" json:"first_name"`
  16. LastName string `db:"last_name" json:"last_name"`
  17. Phone string `db:"phone" json:"phone"`
  18. Status bool `db:"status" json:"status"`
  19. Addrs []UserAddress
  20. }
  21. func main() {
  22. users := []User {
  23. {...User 1 data...},
  24. {...User 2 data...},
  25. }
  26. stmt, err := db.Prepare("INSERT INTO users (id, created_at, updated_at, deleted_at, username, password, first_name, last_name, phone, status) VALUES($1, now(), now(), $2, $3, $4, $5, $6, $7, $8)")
  27. if err != nil {
  28. log.Fatal(err)
  29. }
  30. defer stmt.Close() // Prepared statements take up server resources and should be closed after use.
  31. for id, user := range users {
  32. if _, err := stmt.Exec(id+1, user.Username, user.Password,... other data); err != nil {
  33. log.Fatal(err)
  34. }
  35. }
  36. }

此外,你可以使用Gorm这个强大的包来使用所有关系型数据库。

英文:

I didn't get the structure of your code, but from the main context (inserting query) you should do something like this:

  1. package main
  2. import (
  3. &quot;context&quot;
  4. &quot;database/sql&quot;
  5. &quot;log&quot;
  6. )
  7. var db *sql.DB
  8. type User struct {
  9. ID int `db:&quot;id&quot; json:&quot;id&quot;`
  10. CreatedAt time.Time `db:&quot;created_at&quot; json:&quot;created_at&quot;`
  11. UpdatedAt time.Time `db:&quot;updated_at&quot; json:&quot;updated_at&quot;`
  12. DeletedAt time.Time `db:&quot;deleted_at&quot; json:&quot;deleted_at&quot;`
  13. Username string `db:&quot;username&quot; json:&quot;username&quot;`
  14. Password string `db:&quot;password&quot; json:&quot;password&quot;`
  15. FirstName string `db:&quot;first_name&quot; json:&quot;first_name&quot;`
  16. LastName string `db:&quot;last_name&quot; json:&quot;last_name&quot;`
  17. Phone string `db:&quot;phone&quot; json:&quot;phone&quot;`
  18. Status bool `db:&quot;status&quot; json:&quot;status&quot;`
  19. Addrs []UserAddress
  20. }
  21. func main() {
  22. users := []User {
  23. {...User 1 data...},
  24. {...User 2 data...},
  25. }
  26. stmt, err := db.Prepare(&quot;INSERT INTO users (id, created_at, updated_at, deleted_at, username, password, first_name, last_name, phone, status) VALUES($1, now(), now(), $2, $3, $4, $5, $6, $7, $8)&quot;)
  27. if err != nil {
  28. log.Fatal(err)
  29. }
  30. defer stmt.Close() // Prepared statements take up server resources and should be closed after use.
  31. for id, user := range users {
  32. if _, err := stmt.Exec(id+1, user.Username, user.Password,... other data); err != nil {
  33. log.Fatal(err)
  34. }
  35. }
  36. }

also, you can use the Gorm powerful package for using all relational databases.

答案2

得分: 1

我使用这个助手进行插入操作。

使用以下查询语法:

  1. INSERT INTO checks (
  2. status) VALUES (:status)
  3. returning id;

示例结构体

  1. type Row struct {
  2. Status string `db:"status"`
  3. }
  1. // Insert函数使用查询SQL命令将行插入表中
  2. // 表仅用于日志记录,实际表名在查询中定义
  3. // 函数期望具有命名参数的查询
  4. func Insert(ctx context.Context, row interface{}, query string, table string, tx *sqlx.Tx) (int64, error) {
  5. // 将命名查询转换为本机参数格式
  6. query, args, err := tx.BindNamed(query, row)
  7. if err != nil {
  8. return 0, fmt.Errorf("无法绑定参数插入到表 %q 中:%w", table, err)
  9. }
  10. var id struct {
  11. Val int64 `db:"id"`
  12. }
  13. err = sqlx.GetContext(ctx, tx, &id, query, args...)
  14. if err != nil {
  15. return 0, fmt.Errorf("无法插入到表 %q 中:%w", table, err)
  16. }
  17. return id.Val, nil
  18. }
英文:

I use this helper for inserts.

Works with query syntax as follows:

  1. INSERT INTO checks (
  2. status) VALUES (:status)
  3. returning id;

Sample struct

  1. type Row struct {
  2. Status string `db:&quot;status&quot;`
  3. }
  1. // Insert inserts row into table using query SQL command
  2. // table used only for loging, actual table name defined in query
  3. // function expects Query with named parameters
  4. func Insert(ctx context.Context, row interface{}, query string, table string, tx *sqlx.Tx) (int64, error) {
  5. // convert named query to native parameters format
  6. query, args, err := tx.BindNamed(query, row)
  7. if err != nil {
  8. return 0, fmt.Errorf(&quot;cannot bind parameters for insert into %q: %w&quot;, table, err)
  9. }
  10. var id struct {
  11. Val int64 `db:&quot;id&quot;`
  12. }
  13. err = sqlx.GetContext(ctx, tx, &amp;id, query, args...)
  14. if err != nil {
  15. return 0, fmt.Errorf(&quot;cannot insert into %q: %w&quot;, table, err)
  16. }
  17. return id.Val, nil
  18. }

huangapple
  • 本文由 发表于 2022年6月6日 12:30:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/72513080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定