GORM 查詢

2022-03-04 16:49 更新

檢索單個對象

GORM提供了First,Take,Last方法,以便從數(shù)據(jù)庫中檢索單個對象。當查詢數(shù)據(jù)庫時它添加了LIMIT 1 條件,且沒有找到記錄時,它會返回ErrRecordNotFound錯誤

// 獲取第一條記錄(主鍵升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

// 獲取一條記錄,沒有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;

// 獲取最后一條記錄(主鍵降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

result := db.First(&user)
result.RowsAffected // 返回找到的記錄數(shù)
result.Error        // returns error or nil

// 檢查 ErrRecordNotFound 錯誤
errors.Is(result.Error, gorm.ErrRecordNotFound)

First和Last會根據(jù)主鍵排序,分別查詢第一條和最后一條記錄。只有在目標struct是指針或者通過db.Model()指定model時,該方法才有效。此外,如果相關model沒有定義主鍵,那么將按model的第一個字段進行排序。例如:

var user User
var users []User  

// 有效,因為目標 struct 是指針
db.First(&user)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1

// 有效,因為通過 `db.Model()` 指定了 model
result := map[string]interface{}{}
db.Model(&User{}).First(&result)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1

// 無效
result := map[string]interface{}{}
db.Table("users").First(&result)

// 配合 Take 有效
result := map[string]interface{}{}
db.Table("users").Take(&result)

// 未指定主鍵,會根據(jù)第一個字段排序(即:`Code`)
type Language struct {
  Code string
  Name string
}
db.First(&Language{})
// SELECT * FROM `languages` ORDER BY `languages`.`code` LIMIT 1

用主鍵搜索

如果主鍵是數(shù)字類型,你可以使用內(nèi)聯(lián)條件來檢索對象。傳入字符串參數(shù)時,需要特別注意SQL的注入問題

db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;

db.First(&user, "10")
// SELECT * FROM users WHERE id = 10;

db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);

如果主鍵是字符串(例如像 uuid)查詢將被寫成這樣:

db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";

檢索全部對象

// 獲取全部記錄
result := db.Find(&users)
// SELECT * FROM users;

result.RowsAffected // 返回找到的記錄數(shù),相當于 `len(users)`
result.Error        // returns error

條件

String條件

// 獲取第一條匹配的記錄
db.Where("name = ?", "張三").First(&user)
// SELECT * FROM users WHERE name = '張三' ORDER BY id LIMIT 1;

// 獲取全部匹配的記錄
db.Where("name <> ?", "張三").Find(&users)
// SELECT * FROM users WHERE name <> '張三';

// IN
db.Where("name IN ?", []string{"張三", "張三 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('張三','張三 2');

// LIKE
db.Where("name LIKE ?", "%zs%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%zs%';

// AND
db.Where("name = ? AND age >= ?", "張三", "22").Find(&users)
// SELECT * FROM users WHERE name = '張三' 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';

Struct&Map條件

// Struct
db.Where(&User{Name: "張三", Age: 20}).First(&user)
// SELECT * FROM users WHERE name = "張三" AND age = 20 ORDER BY id LIMIT 1;

// Map
db.Where(map[string]interface{}{"name": "張三", "age": 20}).Find(&users)
// SELECT * FROM users WHERE name = "張三" AND age = 20;

// 主鍵切片條件
db.Where([]int64{20, 21, 22}).Find(&users)
// SELECT * FROM users WHERE id IN (20, 21, 22);

注意:當使用結構作為條件查詢時,GORM只會查詢非零值字段。這意味著如果您的字段值為0,'',false或其他零值,該字段不會被用于構建查詢條件,例如:

db.Where(&User{Name: "張三", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "張三";

如果想要包含零值查詢條件,你可以使用map,其會包含所有key-value的查詢條件,例如:

db.Where(map[string]interface{}{"Name": "張三", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "張三" AND age = 0;

指定結構體查詢字段

當使用struct進行查詢時,你可以通過向Where()傳入struct來指定查詢條件的字段,值,表名,例如:

db.Where(&User{Name: "張三"}, "name", "Age").Find(&users)
// SELECT * FROM users WHERE name = "張三" AND age = 0;

db.Where(&User{Name: "張三"}, "Age").Find(&users)
// SELECT * FROM users WHERE age = 0;

內(nèi)聯(lián)條件

查詢條件也可以被內(nèi)聯(lián)到First和Find之類的方法中,其用法類似于Where

// 根據(jù)主鍵獲取記錄,如果是非整型主鍵
db.First(&user, "id = ?", "string_primary_key")
// SELECT * FROM users WHERE id = 'string_primary_key';

// Plain SQL
db.Find(&user, "name = ?", "張三")
// SELECT * FROM users WHERE name = "張三";

db.Find(&users, "name <> ? AND age > ?", "張三", 20)
// SELECT * FROM users WHERE name <> "張三" AND age > 20;

// Struct
db.Find(&users, User{Age: 20})
// SELECT * FROM users WHERE age = 20;

// Map
db.Find(&users, map[string]interface{}{"age": 20})
// SELECT * FROM users WHERE age = 20;

Not條件

構建NOT條件,用法與 Where 類似

db.Not("name = ?", "張三").First(&user)
// SELECT * FROM users WHERE NOT name = "張三" ORDER BY id LIMIT 1;

// Not In
db.Not(map[string]interface{}{"name": []string{"張三", "張三 2"}}).Find(&users)
// SELECT * FROM users WHERE name NOT IN ("張三", "張三 2");

// Struct
db.Not(User{Name: "張三", Age: 18}).First(&user)
// SELECT * FROM users WHERE name <> "張三" AND age <> 18 ORDER BY id LIMIT 1;

// 不在主鍵切片中的記錄
db.Not([]int64{1,2,3}).First(&user)
// SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;

Or條件

db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';

// Struct
db.Where("name = '張三'").Or(User{Name: "張三 2", Age: 18}).Find(&users)
// SELECT * FROM users WHERE name = '張三' OR (name = '張三 2' AND age = 18);

// Map
db.Where("name = '張三'").Or(map[string]interface{}{"name": "張三 2", "age": 18}).Find(&users)
// SELECT * FROM users WHERE name = '張三' OR (name = '張三 2' AND age = 18);

選擇特定字段

Select允許你指定從數(shù)據(jù)庫中檢索哪些字段,默認情況下,GORM會檢索所有字段

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

指定從數(shù)據(jù)庫檢索記錄時的排序方式

db.Order("age desc, name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;

// 多個 order
db.Order("age desc").Order("name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;

db.Clauses(clause.OrderBy{
  Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true},
}).Find(&User{})
// SELECT * FROM users ORDER BY FIELD(id,1,2,3)

Limit&Offset

Limit指定獲取記錄的最大數(shù)量Offset指定在開始返回記錄之前要跳過的記錄數(shù)量

db.Limit(3).Find(&users)
// SELECT * FROM users LIMIT 3;

// 通過 -1 消除 Limit 條件
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
// SELECT * FROM users LIMIT 10; (users1)
// SELECT * FROM users; (users2)

db.Offset(3).Find(&users)
// SELECT * FROM users OFFSET 3;

db.Limit(10).Offset(5).Find(&users)
// SELECT * FROM users OFFSET 5 LIMIT 10;

// 通過 -1 消除 Offset 條件
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
// SELECT * FROM users OFFSET 10; (users1)
// SELECT * FROM users; (users2)


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號