男神鹏:golang gorm 安装以及基础使用
1. 安装
go get -u github.com/jinzhu/gorm
2.声明module
type User struct {
gorm.Model
Name string
Age sql.NullInt64
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // 设置属性长度 255
MemberNumber *string `gorm:"unique;not null"` //设置唯一并且非空
Num int `gorm:"AUTO_INCREMENT"` //设置自增
Address string `gorm:"index:addr"` //给字段address创建索引,名’addr’
IgnoreMe int `gorm:"-"` // 忽略这个属性
}
gorm.Model 包含如下属性: ID, CreatedAt, UpdatedAt, DeletedAt.
// gorm.Model 定义
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
GORM使用字段名为ID作为默认主键。
type User struct {
ID string
Name string
}
//设置AnimalID作为主键
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
在声明模型时,tags是可选的。GORM支持以下tags。
**Tag** | **Description** |
---|---|
Column | Specifies column name |
Type | Specifies column data type |
Size | Specifies column size, default 255 |
PRIMARY_KEY | Specifies column as primary key |
UNIQUE | Specifies column as unique |
DEFAULT | Specifies column default value |
PRECISION | Specifies column precision |
NOT NULL | Specifies column as NOT NULL |
AUTO_INCREMENT | Specifies column auto incrementable or not |
INDEX | Create index with or without name, same name creates composite indexes |
UNIQUE_INDEX | Like INDEX, create unique index |
EMBEDDED | Set struct as embedded |
EMBEDDED_PREFIX | Set embedded struct’s prefix name |
- | Ignore this fields |
3. 关联的结构标记
4.表名是结构体名称的复数形式
type User struct {
}
其默认表名为users
可以设置表名为自定义名称。
func (User) TableName() string {
return "profiles"
}
如果不想使用这个复数形式,可以设置为单数,传true即可。
db.SingularTable(true)
也可以这样定义:
db.Table("users").CreateTable(&User{})
使用user的结构创建表名为users。
5. 时间戳
CreatedAt
一条记录第一次被创建的时候会修改该值。
// will set `CreatedAt` to current time
db.Create(&user)
// To change its value, you could use `Update`
db.Model(&user).Update("CreatedAt", time.Now())
UpdatedAt
当这条记录被修改的时候,会修改该字段。
// will set `UpdatedAt` to current time
db.Save(&user)
// will set `UpdatedAt` to current time
db.Model(&user).Update("name", "jinzhu")
DeletedAt
对于具有deleted_at字段的模型,当对该实例调用Delete时,不会真正从数据库中删除它,而是将其DeletedAt字段设置为当前时间
6.连接数据库
要连接到数据库,需要先导入数据库的驱动程序。
import _ ”github.com/go-sql-driver/mysql“
GORM包装了一些驱动程序,以便更容易记住导入路径。因此您可以使用以下命令导入mysql驱动程序:
import _ "github.com/jinzhu/gorm/dialects/mysql"
// import _ "github.com/jinzhu/gorm/dialects/postgres"
// import _ "github.com/jinzhu/gorm/dialects/sqlite"
// import _ "github.com/jinzhu/gorm/dialects/mssql"
下面主要讲下MySQL
注意:
为了正确地处理time.time,需要将parseTime作为一个参数。
为了完全支持UTF-8编码,需要将charset=utf8更改为charset=utf8mb4。
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
db, err := gorm.Open("mysql", "user:password@(localhost)/dbname?charset=utf8&parseTime=True&loc=Local")
defer db.Close()
}
7. Create
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
db.NewRecord(user) // => 当主键为空时返回true
db.Create(&user)
db.NewRecord(user) // => user创建后返回false
默认值:
type Animal struct {
ID int64
Name string `gorm:"default:'galeone'"`
Age int64
}
然后插入的SQL将排除那些没有值或零的字段
var animal = Animal{Age: 99, Name: ""}
db.Create(&animal)
// INSERT INTO animals("age") values('99');
// SELECT name from animals WHERE ID=111; // the returning primary key is 111
// animal.Name => 'galeone'
注意:
所有具有零值的字段(如0、“”或其他零值)都不会保存到数据库中,而是使用其默认值。如果要避免这种情况,请考虑使用指针类型
// Use pointer value
type User struct {
gorm.Model
Name string
Age *int `gorm:"default:18"`
}
// Use scanner/valuer
type User struct {
gorm.Model
Name string
Age sql.NullInt64 `gorm:"default:18"`
}
使用钩子
如果要在BeforeCreate钩子中更新字段的值,可以使用scope.SetColumn,例如:
func (user *User) BeforeCreate(scope *gorm.Scope) error {
scope.SetColumn("ID", uuid.New())
return nil
}
8. Query
// Get first record, order by primary key
db.First(&user)
//// SELECT * FROM users ORDER BY id LIMIT 1;
// Get one record, no specified order
db.Take(&user)
//// SELECT * FROM users LIMIT 1;
// Get last record, order by primary key
db.Last(&user)
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
// Get all records
db.Find(&users)
//// SELECT * FROM users;
// Get record with primary key (only works for integer primary key)
db.First(&user, 10)
//// SELECT * FROM users WHERE id = 10;
9. Where
原始sql
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
//// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu';
// <>
db.Where("name <> ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
//// SELECT * FROM users WHERE name in ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
//// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
//// SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
//// SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
10. Struct & Map
// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 ORDER BY id LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
// Slice of primary keys
db.Where([]int64{20, 21, 22}).Find(&users)
//// SELECT * FROM users WHERE id IN (20, 21, 22);
注意:
当使用struct进行查询时,GORM将只使用那些字段具有非零值的查询,这意味着如果字段的值为0、’’、false或其他零值,则不会使用它来构建查询条件,例如:
db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
//// SELECT * FROM users WHERE name = "jinzhu";
11. 添加额外查询项
db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10)
//// SELECT * FROM users WHERE id = 10 FOR UPDATE;
12. FirstOrInit
获取第一个匹配的记录,或使用给定条件初始化新记录(仅适用于结构、map)
// Unfound
db.FirstOrInit(&user, User{Name: "non_existing"})
//// user -> User{Name: "non_existing"}
// Found
db.Where(User{Name: "Jinzhu"}).FirstOrInit(&user)
//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
13. Attrs
如果找不到记录,则使用参数初始化结构
// Unfound
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
//// SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
//// user -> User{Name: "non_existing", Age: 20}
db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)
//// SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
//// user -> User{Name: "non_existing", Age: 20}
// Found
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
//// SELECT * FROM USERS WHERE name = jinzhu' ORDER BY id LIMIT 1;
//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
14. Assign
将参数赋给结构,不管是否找到它。
// Unfound
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
//// user -> User{Name: "non_existing", Age: 20}
// Found
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user)
//// SELECT * FROM USERS WHERE name = jinzhu' ORDER BY id LIMIT 1;
//// user -> User{Id: 111, Name: "Jinzhu", Age: 30}
15. FirstOrCreate
获取第一个匹配的记录,或使用给定条件创建一个新记录(仅适用于结构、映射条件)。
// Unfound
db.FirstOrCreate(&user, User{Name: "non_existing"})
//// INSERT INTO "users" (name) VALUES ("non_existing");
//// user -> User{Id: 112, Name: "non_existing"}
// Found
db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user)
//// user -> User{Id: 111, Name: "Jinzhu"}
16.高级查询
SubQuery
db.Where("amount > ?", db.Table("orders").Select("AVG(amount)").Where("state = ?", "paid").SubQuery()).Find(&orders)
// SELECT * FROM "orders" WHERE "orders"."deleted_at" IS NULL AND (amount > (SELECT AVG(amount) FROM "orders" WHERE (state = 'paid')));
Select
db.Select("name, age").Find(&users)
//// SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
//// SELECT name, age FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
//// SELECT COALESCE(age,'42') FROM users;
Order
指定从数据库检索记录时的顺序,将reorder(第二个参数)设置为true以覆盖定义的条件。
db.Order("age desc, name").Find(&users)
//// SELECT * FROM users ORDER BY age desc, name;
// Multiple orders
db.Order("age desc").Order("name").Find(&users)
//// SELECT * FROM users ORDER BY age desc, name;
// ReOrder
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
//// SELECT * FROM users ORDER BY age desc; (users1)
//// SELECT * FROM users ORDER BY age; (users2)
Limit
指定要检索的最大记录数。
db.Limit(3).Find(&users)
//// SELECT * FROM users LIMIT 3;
// Cancel limit condition with -1
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
//// SELECT * FROM users LIMIT 10; (users1)
//// SELECT * FROM users; (users2)
Offset
指定开始返回记录之前要跳过的记录数。
db.Offset(3).Find(&users)
//// SELECT * FROM users OFFSET 3;
// Cancel offset condition with -1
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
//// SELECT * FROM users OFFSET 10; (users1)
//// SELECT * FROM users; (users2)
Count
获取模型的记录数。
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
//// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)
//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)
db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
//// SELECT count(*) FROM users WHERE name = 'jinzhu'; (count)
db.Table("deleted_users").Count(&count)
//// SELECT count(*) FROM deleted_users;
db.Table("deleted_users").Select("count(distinct(name))").Count(&count)
//// SELECT count( distinct(name) ) FROM deleted_users; (count)
Group &Having
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
for rows.Next() {
...
}
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
for rows.Next() {
...
}
type Result struct {
Date time.Time
Total int64
}
db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
Joins
rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows()
for rows.Next() {
...
}
db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
// multiple joins with parameter
db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
Pluck
将模型中的单个列作为映射查询,如果要查询多个列,则应改用Scan。
var ages []int64
db.Find(&users).Pluck("age", &ages)
var names []string
db.Model(&User{}).Pluck("name", &names)
db.Table("deleted_users").Pluck("name", &names)
// Requesting more than one column? Do it like this:
db.Select("name, age").Find(&users)
Scan
将结果扫描到另一个结构中。
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", "Antonio").Scan(&result)
// Raw SQL
db.Raw("SELECT name, age FROM users WHERE name = ?", "Antonio").Scan(&result)
Update
修改所有属性。Save将在执行更新SQL时包含所有字段,即使没有更改。
db.First(&user)
user.Name = "jinzhu2"
user.Age = 100
db.Save(&user)
//// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
更新更改的字段
如果只想更新已更改的字段,可以使用update,Updates。
// Update single attribute if it is changed
db.Model(&user).Update("name", "hello")
//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
// Update single attribute with combined conditions
db.Model(&user).Where("active = ?", true).Update("name", "hello")
//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;
// Update multiple attributes with `map`, will only update those changed fields
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
//// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
// Update multiple attributes with `struct`, will only update those changed & non blank fields
db.Model(&user).Updates(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// WARNING when update with struct, GORM will only update those fields that with non blank value
// For below Update, nothing will be updated as "", 0, false are blank values of their types
db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})
修改列不用钩子
以上更新操作将执行模型的BeforeUpdate、AfterUpdate方法,更新其UpdatedAt时间戳,更新时保存其关联,如果不想调用它们,可以使用UpdateColumn、UpdateColumns。
// Update single attribute, similar with `Update`
db.Model(&user).UpdateColumn("name", "hello")
//// UPDATE users SET name='hello' WHERE id = 111;
// Update multiple attributes, similar with `Updates`
db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18 WHERE id = 111;
批量修改
批量更新时不会运行钩子。
db.Table("users").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})
//// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);
// Update with struct only works with none zero values, or use map[string]interface{}
db.Model(User{}).Updates(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18;
// Get updated records count with `RowsAffected`
db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected
使用 SQL **表达式
DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100))
//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';
DB.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)})
//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';
DB.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
//// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2';
DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
//// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2' AND quantity > 1;
使用钩子更改值
如果要使用BeforeUpdate、BeforeSave更改挂钩中的更新值,可以使用scope.SetColumn,例如:
func (user *User) BeforeSave(scope *gorm.Scope) (err error) {
if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil {
scope.SetColumn("EncryptedPassword", pw)
}
}
Delete
如果一个模型有一个DeletedAt字段,它将自动获得一个软删除能力!调用Delete时,不会从数据库中永久删除记录;相反,DeletedAt的值将设置为当前时间。
db.Delete(&user)
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
// Batch Delete
db.Where("age = ?", 20).Delete(&User{})
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
// Soft deleted records will be ignored when query them
db.Where("age = 20").Find(&user)
//// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
// Find soft deleted records with Unscoped
db.Unscoped().Where("age = 20").Find(&users)
//// SELECT * FROM users WHERE age = 20;
永久删除记录
// Delete record permanently with Unscoped
db.Unscoped().Delete(&order)
//// DELETE FROM orders WHERE id=10;
Belongs To
归属于关联与另一个模型建立一对一的连接,这样声明模型的每个实例都“属于”另一个模型的一个实例。
例如,如果应用程序包含用户和配置文件,并且每个配置文件都可以指定给一个用户。
type User struct {
gorm.Model
Name string
}
// `Profile` belongs to `User`, `UserID` is the foreign key
type Profile struct {
gorm.Model
UserID int
User User
Name string
}
外键
若要定义“属于”关系,外键必须存在,默认外键使用所有者的类型名及其主键。
对于上面的示例,要定义属于用户的模型,外键应该是UserID。
GORM提供了一种自定义外键的方法,例如:
type User struct {
gorm.Model
Name string
}
type Profile struct {
gorm.Model
Name string
User User `gorm:"foreignkey:UserRefer"` // use UserRefer as foreign key
UserRefer uint
}
关联外键
对于归属关系,GORM通常使用所有者的主键作为外键的值,例如,它是用户的ID。
将配置文件分配给用户时,GORM会将用户的ID保存到配置文件的UserID字段中。可以使用标记关联外键进行更改,例如:
type User struct {
gorm.Model
Refer string
Name string
}
type Profile struct {
gorm.Model
Name string
User User `gorm:"association_foreignkey:Refer"` // use Refer as association foreign key
UserRefer string
}
使用 belong to
db.Model(&user).Related(&profile)
//// SELECT * FROM profiles WHERE user_id = 111; // 111 is user's ID
ManyToMany
**Foreign Keys
type CustomizePerson struct {
IdPerson string `gorm:"primary_key:true"`
Accounts []CustomizeAccount `gorm:"many2many:PersonAccount;association_foreignkey:idAccount;foreignkey:idPerson"`
}
type CustomizeAccount struct {
IdAccount string `gorm:"primary_key:true"`
Name string
}
它将为这两个结构创建多个关系,并将它们的关系保存到联接表personAccount带有外键的customize_person_id_person和customize_account。
Jointable ForeignKey
如果要更改联接表的外键,可以使用标记关联。
type CustomizePerson struct {
IdPerson string `gorm:"primary_key:true"`
Accounts []CustomizeAccount `gorm:"many2many:PersonAccount;foreignkey:idPerson;association_foreignkey:idAccount;association_jointable_foreignkey:account_id;jointable_foreignkey:person_id;"`
}
type CustomizeAccount struct {
IdAccount string `gorm:"primary_key:true"`
Name string
}
Self-Referencing
要定义自引用的many2many关系,必须在联接表中更改关联的外键。要使其与使用结构名称及其主键生成的源外键不同,例如:
type People struct {
gorm.Model
Friends []*People `gorm:"many2many:friendships;association_jointable_foreignkey:friend_id"`
}
GORM将创建一个具有外键people_id和friend_id的联接表,并使用它保存用户的自引用关系。
17. 错误处理
Error Handling
GORM中的错误处理不同于惯用的Go代码,因为它的API是可链接的,但是仍然易于实现。
如果发生任何错误,GORM将设置*GORM.DB的错误字段,可以这样检查:
f err := db.Where("name = ?", "jinzhu").First(&user).Error; err != nil {
// error handling...
}
RecordNotFound Error
GORM提供了处理RecordNotFound错误的快捷方式。如果有几个错误,它将检查其中是否有一个是RecordNotFound错误。
// Check if returns RecordNotFound error
db.Where("name = ?", "hello world").First(&user).RecordNotFound()
if db.Model(&user).Related(&credit_card).RecordNotFound() {
// record not found
}
if err := db.Where("name = ?", "jinzhu").First(&user).Error; gorm.IsRecordNotFoundError(err) {
// record not found
}
18 事务
GORM默认情况下在事务中执行单个创建、更新、删除操作,以确保数据库数据的完整性。如果要将多个create、update、delete视为一个原子操作,则为此进行事务处理。
func CreateAnimals(db *gorm.DB) error {
return db.Transaction(func(tx *gorm.DB) error {
// do some database operations in the transaction (use 'tx' from this point, not 'db')
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
// return any error will rollback
return err
}
if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
return err
}
// return nil will commit
return nil
})
}
19. Migration
自动迁移架构,使架构保持最新。
注意:自动迁移将只创建表、缺少列和缺少索引,并且不会更改现有列的类型或删除未使用的列以保护数据。
db.AutoMigrate(&User{})
db.AutoMigrate(&User{}, &Product{}, &Order{})
// Add table suffix when create tables
db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})
20. Schema Methods
判断表是否存在。
// Check model `User`'s table exists or not
db.HasTable(&User{})
// Check table `users` exists or not
db.HasTable("users")
创建表。
// Create table for model `User`
db.CreateTable(&User{})
// will append "ENGINE=InnoDB" to the SQL statement when creating table `users`
db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{})
删除表。
// Drop model `User`'s table
db.DropTable(&User{})
// Drop table `users`
db.DropTable("users")
// Drop model's `User`'s table and table `products`
db.DropTableIfExists(&User{}, "products")
修改列。
// change column description's data type to `text` for model `User`
db.Model(&User{}).ModifyColumn("description", "text")
添加索引。
// Add index for columns `name` with given name `idx_user_name`
db.Model(&User{}).AddIndex("idx_user_name", "name")
// Add index for columns `name`, `age` with given name `idx_user_name_age`
db.Model(&User{}).AddIndex("idx_user_name_age", "name", "age")
// Add unique index
db.Model(&User{}).AddUniqueIndex("idx_user_name", "name")
// Add unique index for multiple columns
db.Model(&User{}).AddUniqueIndex("idx_user_name_age", "name", "age")
删除索引。
// Remove index
db.Model(&User{}).RemoveIndex("idx_user_name")
复合主键。
将多个字段设置为主键以启用复合主键。
type Product struct {
ID string `gorm:"primary_key"`
LanguageCode string `gorm:"primary_key"`
Code string
Name string
}
注意,带有primary_key标记的整数字段在默认情况下是自动递增的。这可能导致多个自动递增的整数主键,而不是单个复合主键。
要创建包含int的复合主键,需要关闭int字段的自动递增:
type Product struct {
CategoryID uint64 `gorm:"primary_key;auto_increment:false"`
TypeID uint64 `gorm:"primary_key;auto_increment:false"`
}