条件查询

条件查询是日常开发中最常用的功能。GORM 的 Where 方法灵活多样,能满足各种场景需求。

基本条件

字符串条件:

db.Where("name = ?", "张三").First(&user)
db.Where("age > ?", 20).Find(&users)
db.Where("name <> ?", "张三").Find(&users)

使用占位符 ? 防止 SQL 注入,这是必须遵守的安全规范。

多条件组合

AND 条件:

db.Where("name = ? AND age > ?", "张三", 20).Find(&users)

链式调用自动 AND:

db.Where("name = ?", "张三").Where("age > ?", 20).Find(&users)

OR 条件:

db.Where("name = ?", "张三").Or("name = ?", "李四").Find(&users)

组合 OR:

db.Where("name = ?", "张三").Or(
    db.Where("age > ?", 20).Where("status = ?", "active"),
).Find(&users)

IN 条件

db.Where("name IN ?", []string{"张三", "李四", "王五"}).Find(&users)
db.Where("id IN ?", []int{1, 2, 3}).Find(&users)

LIKE 模糊查询

db.Where("name LIKE ?", "%张%").Find(&users)
db.Where("name LIKE ?", "张%").Find(&users)
db.Where("name LIKE ?", "%三").Find(&users)

BETWEEN 范围

db.Where("age BETWEEN ? AND ?", 18, 30).Find(&users)
db.Where("created_at BETWEEN ? AND ?", startTime, endTime).Find(&users)

NULL 判断

db.Where("deleted_at IS NULL").Find(&users)
db.Where("email IS NOT NULL").Find(&users)

结构体条件

用结构体作为条件:

db.Where(&User{Name: "张三", Age: 20}).First(&user)

注意:结构体条件会忽略零值。Age: 0 不会被加入查询条件。

Map 条件

用 map 作为条件,零值也会参与:

db.Where(map[string]interface{}{"name": "张三", "age": 0}).Find(&users)

主键条件

直接传主键:

db.First(&user, 1)
db.Find(&users, []int{1, 2, 3})

Not 条件

db.Not("name", "张三").Find(&users)
db.Not("name IN ?", []string{"张三", "李四"}).Find(&users)
db.Not(map[string]interface{}{"name": "张三", "age": 20}).Find(&users)

Or 条件

db.Where("name = ?", "张三").Or("age > ?", 30).Find(&users)

嵌套 Or:

db.Where(
    db.Where("name = ?", "张三").Or("name = ?", "李四"),
).Where("age > ?", 20).Find(&users)

条件分组

用括号分组:

db.Where("(name = ? OR name = ?) AND age > ?", "张三", "李四", 20).Find(&users)

动态条件

根据条件动态构建查询:

query := db.Model(&User{})

if name != "" {
    query = query.Where("name = ?", name)
}
if minAge > 0 {
    query = query.Where("age >= ?", minAge)
}
if maxAge > 0 {
    query = query.Where("age <= ?", maxAge)
}

var users []User
query.Find(&users)

复杂条件示例

实际业务中的复杂查询:

func SearchUsers(db *gorm.DB, params SearchParams) ([]User, error) {
    query := db.Model(&User{})

    if params.Keyword != "" {
        query = query.Where("name LIKE ? OR email LIKE ?", 
            "%"+params.Keyword+"%", 
            "%"+params.Keyword+"%")
    }

    if len(params.Statuses) > 0 {
        query = query.Where("status IN ?", params.Statuses)
    }

    if params.MinAge > 0 {
        query = query.Where("age >= ?", params.MinAge)
    }
    if params.MaxAge > 0 {
        query = query.Where("age <= ?", params.MaxAge)
    }

    if !params.StartTime.IsZero() {
        query = query.Where("created_at >= ?", params.StartTime)
    }
    if !params.EndTime.IsZero() {
        query = query.Where("created_at <= ?", params.EndTime)
    }

    var users []User
    return users, query.Find(&users).Error
}

条件复用

把常用条件封装成函数:

func ActiveUsers(db *gorm.DB) *gorm.DB {
    return db.Where("status = ?", "active").Where("deleted_at IS NULL")
}

func AdultUsers(db *gorm.DB) *gorm.DB {
    return db.Where("age >= ?", 18)
}

var users []User
ActiveUsers(AdultUsers(db)).Find(&users)

原生 SQL 条件

复杂条件直接写 SQL:

db.Where("DATE(created_at) = CURDATE()").Find(&users)
db.Where("YEAR(created_at) = YEAR(NOW())").Find(&users)

小结

条件查询是 GORM 的核心功能。掌握各种条件的写法,能应对大部分业务场景。注意 SQL 注入问题,始终使用占位符。