Gorm中Model(&Usertable).Create(data)如何传入正确表名?
问题描述
尝试向GORM定义的表中插入数据时出现表名空的错误,以下是相关信息:
包结构
gorm |- server |- insertRow.go |- pkg |- models |- mytable.go |- database | - connectdb.go
mytable.go 代码
package models type Usertable struct { Firstname string `gorm:"column:firstname"` Lastname string `gorm:"column:lastname"` } func (fmap *Usertable) TableName() string { return "usertable" }
insertRow.go 初始代码
package main import ( "fmt" "gorm/pkg/models" "gorm/pkg/database" ) func main() { params := map[string]interface{} { "Firstname" : "MyFirstName", "Lastname" : "LastName" , } db, _ := database.NewStorage("postgres", "testdb") var user models.Usertable err := db.DB.Debug().Model(&user).Create(params) if err != nil { fmt.Println("Error :=", err) } else { fmt.Println("Success") } }
数据库表定义
testdb=# \d+ usertable Table "public.usertable" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -----------+------+-----------+----------+---------+----------+--------------+------------- firstname | text | | | | extended | | lastname | text | | | | extended | |
执行错误信息
(/root/gorm/cloudOps/server/testDB/insertRow.go:17) [2023-09-23 23:51:26] pq: zero-length delimited identifier at or near """" (/root/gorm/cloudOps/server/testDB/insertRow.go:17) [2023-09-23 23:51:26] [0.45ms] **INSERT INTO "" DEFAULT VALUES RETURNING "".*** [0 rows affected or returned ] Error := &{{{0 0} 0 0 {{} 0} {{} 0}} map[Firstname:MyFirstName Lastname:LastName] pq: zero-length delimited identifier at or near """" 0 0xc0000a4b60 false 2 {0xc0001a3d60} 0xc0001e8420 {{0 0} {[] {} 0xc00021cc20} map[] 0} 0xc0000a4c30 <nil> 0xc0000a2c78 false <nil>}
可见生成的INSERT语句中表名为空,尝试了以下写法但结果相同:
package main import ( "fmt" // "gorm/pkg/models" "gorm/pkg/database" "gorm.io/gorm" ) type Usertable struct { gorm.Model Firstname string `gorm:"column:firstname"` Lastname string `gorm:"column:lastname"` } func main() { params := map[string]interface{} { "Firstname" : "MyFirstName", "Lastname" : "LastName" , } db, _ := database.NewStorage("postgres", "testdb") err := db.DB.Debug().Model(&Usertable{}).Create(params) if err != nil { fmt.Println("Error :=", err) } else { fmt.Println("Success") } }
请问插入命令存在什么问题?如何向Create调用传递正确的表名?
解决方案
问题核心:用map作为Create参数时,GORM无法通过Model指定的结构体获取表名。因为Create(map)的写法会让GORM忽略Model里的表元信息,转而尝试从映射中推断,但映射没有表名相关数据,最终生成空表名的SQL。
两种解决办法:
方法1:用结构体实例替代map作为Create参数
直接构造Usertable结构体实例,GORM会自动识别表名(包括TableName()方法定义的名称):
func main() { db, err := database.NewStorage("postgres", "testdb") if err != nil { fmt.Println("数据库连接失败:", err) return } user := models.Usertable{ Firstname: "MyFirstName", Lastname: "LastName", } err = db.DB.Debug().Create(&user).Error if err != nil { fmt.Println("插入错误:", err) } else { fmt.Println("插入成功") } }
方法2:必须用map时,显式指定表名
使用Table()方法直接指定表名,替代Model()的作用:
func main() { params := map[string]interface{}{ "Firstname": "MyFirstName", "Lastname": "LastName", } db, err := database.NewStorage("postgres", "testdb") if err != nil { fmt.Println("数据库连接失败:", err) return } // 直接用Table指定表名 err = db.DB.Debug().Table("usertable").Create(params).Error if err != nil { fmt.Println("插入错误:", err) } else { fmt.Println("插入成功") } }
额外注意事项
- 不要忽略
database.NewStorage的错误返回,必须检查连接是否成功,避免基于无效DB实例执行操作。 - 第一种方法更贴合GORM设计范式,能利用结构体的标签验证、自动字段映射等特性,优先推荐使用。
内容的提问来源于stack exchange,提问作者Ravindra Rao
相关产品推荐
相关产品推荐

