除了 AutoMigrate,GORM 还提供了手动创建表的方法。更精细的控制,适合复杂场景。
手动创建表:
db.CreateTable(&User{})
表不存在时创建,存在时报错。
if !db.Migrator().HasTable(&User{}) {
db.CreateTable(&User{})
}
或者:
if !db.Migrator().HasTable("users") {
db.CreateTable(&User{})
}
指定表选项:
db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4").CreateTable(&User{})
MySQL 常用选项:
db.Set("gorm:table_options", `
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci
AUTO_INCREMENT=1000
`).CreateTable(&User{})
PostgreSQL:
db.Set("gorm:table_options", "WITH (OIDS=FALSE)").CreateTable(&User{})
创建表前,完整定义模型:
type User struct {
ID uint `gorm:"primaryKey;autoIncrement;comment:用户ID"`
Name string `gorm:"type:varchar(50);not null;comment:用户名"`
Email string `gorm:"type:varchar(100);uniqueIndex;comment:邮箱"`
Password string `gorm:"type:varchar(255);not null;comment:密码"`
Age int `gorm:"default:18;comment:年龄"`
Status string `gorm:"type:enum('active','inactive');default:'active';comment:状态"`
Bio string `gorm:"type:text;comment:简介"`
CreatedAt time.Time `gorm:"comment:创建时间"`
UpdatedAt time.Time `gorm:"comment:更新时间"`
DeletedAt gorm.DeletedAt `gorm:"index;comment:删除时间"`
}
func (User) TableName() string {
return "users"
}
生成的 SQL:
CREATE TABLE `users` (
`id` INT AUTO_INCREMENT COMMENT '用户ID',
`name` VARCHAR(50) NOT NULL COMMENT '用户名',
`email` VARCHAR(100) COMMENT '邮箱',
`password` VARCHAR(255) NOT NULL COMMENT '密码',
`age` INT DEFAULT 18 COMMENT '年龄',
`status` ENUM('active','inactive') DEFAULT 'active' COMMENT '状态',
`bio` TEXT COMMENT '简介',
`created_at` DATETIME COMMENT '创建时间',
`updated_at` DATETIME COMMENT '更新时间',
`deleted_at` DATETIME COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `idx_users_email` (`email`),
INDEX `idx_users_deleted_at` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
创建多个表:
db.CreateTable(&User{}, &Order{}, &Product{})
或者分别创建:
db.CreateTable(&User{})
db.CreateTable(&Order{})
db.CreateTable(&Product{})
创建带外键约束的表:
type Order struct {
ID uint
UserID uint
User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
Amount float64
}
db.CreateTable(&User{})
db.CreateTable(&Order{})
外键约束在创建 Order 表时建立。
模型中定义索引:
type User struct {
ID uint
Name string `gorm:"index:idx_name"`
Email string `gorm:"uniqueIndex"`
Age int `gorm:"index:idx_name_age,priority:2"`
City string `gorm:"index:idx_name_age,priority:1"`
}
复合索引 idx_name_age 包含 city 和 age,优先级决定顺序。
创建临时表:
db.Table("temp_users").CreateTable(&User{})
但这不会创建真正的临时表。要创建临时表需要原生 SQL:
db.Exec(`
CREATE TEMPORARY TABLE temp_users (
id INT PRIMARY KEY,
name VARCHAR(50)
)
`)
自定义表名:
func (User) TableName() string {
return "sys_users"
}
动态表名:
func (u *User) TableName() string {
return "users_" + u.TenantID
}
全局表名策略:
db.NamingStrategy = schema.NamingStrategy{
TablePrefix: "t_",
SingularTable: true,
}
db.DropTable(&User{})
db.DropTable("users")
db.DropTableIfExists(&User{})
db.Migrator().DropTable(&User{}, &Order{}, &Product{})
初始化数据库
func InitDatabase(db *gorm.DB) error {
models := []interface{}{
&User{},
&Role{},
&Permission{},
&Order{},
&Product{},
}
for _, model := range models {
if !db.Migrator().HasTable(model) {
if err := db.CreateTable(model).Error; err != nil {
return err
}
}
}
return nil
}
带检查的创建
func EnsureTable(db *gorm.DB, model interface{}) error {
if db.Migrator().HasTable(model) {
return nil
}
return db.CreateTable(model).Error
}
手动创建表提供更精细的控制。配合完整的模型定义,可以创建复杂的表结构。