Golang中如何动态生成select查询语句

Golang中如何动态生成select查询语句 我使用这个Go语言的生成器(https://github.com/Masterminds/squirrel),需要创建一个SQL的WHERE条件解析器。

假设我有如下用户输入:

  • Bar.Alpha = 7
  • Foo.Bar.X = ‘hello’
  • Foo.Bar.Beta > 21 AND Alpha.Bar != ‘hello’
  • Alice.IsActive AND Bob.LastHash = ‘ab5534b’
  • Alice.Name ~ ‘A.’ OR Bob.LastName !~ 'Bill.
  • Field1 = “foo” AND Field2 != 7 OR Field3 > 11.7

用户的查询中可能包含大量的AND / OR。如何动态生成它们?谢谢。


更多关于Golang中如何动态生成select查询语句的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你所说的“动态生成它们”,是指给定 Foo.Bar.X = 'hello' 后,需要为这个约束生成 SQL 的 WHERE 子句吗?你还需要生成 JOIN 子句吗?

更多关于Golang中如何动态生成select查询语句的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中动态生成SELECT查询的WHERE条件,可以使用squirrel的sqlizer接口和条件构建方法。以下是几种常见情况的示例:

1. 基础条件构建

import sq "github.com/Masterminds/squirrel"

// 简单等于条件
where := sq.Eq{"Bar.Alpha": 7}
sql, args, _ := sq.Select("*").From("table").Where(where).ToSql()
// SELECT * FROM table WHERE Bar.Alpha = ?

// 多个AND条件
where := sq.And{
    sq.Eq{"Bar.Alpha": 7},
    sq.Eq{"Foo.Bar.X": "hello"},
}

2. 处理AND/OR混合条件

// AND/OR混合条件示例
conditions := sq.Or{
    sq.And{
        sq.Eq{"Alice.IsActive": true},
        sq.Eq{"Bob.LastHash": "ab5534b"},
    },
    sq.And{
        sq.Like{"Alice.Name": "A%"},
        sq.NotLike{"Bob.LastName": "Bill%"},
    },
}

sql, args, _ := sq.Select("*").From("users").Where(conditions).ToSql()

3. 动态构建复杂WHERE条件

func buildDynamicWhere(filters []Filter) sq.Sqlizer {
    var conditions []sq.Sqlizer
    
    for _, filter := range filters {
        switch filter.Operator {
        case "=":
            conditions = append(conditions, sq.Eq{filter.Field: filter.Value})
        case "!=":
            conditions = append(conditions, sq.NotEq{filter.Field: filter.Value})
        case ">":
            conditions = append(conditions, sq.Gt{filter.Field: filter.Value})
        case "<":
            conditions = append(conditions, sq.Lt{filter.Field: filter.Value})
        case "~":
            conditions = append(conditions, sq.Like{filter.Field: filter.Value})
        case "!~":
            conditions = append(conditions, sq.NotLike{filter.Field: filter.Value})
        }
    }
    
    return sq.And(conditions)
}

// 使用示例
filters := []Filter{
    {Field: "Field1", Operator: "=", Value: "foo"},
    {Field: "Field2", Operator: "!=", Value: 7},
    {Field: "Field3", Operator: ">", Value: 11.7},
}

where := buildDynamicWhere(filters)
sql, args, _ := sq.Select("*").From("table").Where(where).ToSql()

4. 处理嵌套AND/OR逻辑

// 解析类似 "Field1 = 'foo' AND Field2 != 7 OR Field3 > 11.7" 的字符串
func parseComplexCondition(conditionStr string) sq.Sqlizer {
    // 这里需要实现自己的解析逻辑
    // 返回类似这样的结构:
    return sq.Or{
        sq.And{
            sq.Eq{"Field1": "foo"},
            sq.NotEq{"Field2": 7},
        },
        sq.Gt{"Field3": 11.7},
    }
}

// 构建查询
where := parseComplexCondition("Field1 = 'foo' AND Field2 != 7 OR Field3 > 11.7")
query := sq.Select("*").From("table").Where(where)

5. 完整示例:处理用户输入条件

type Condition struct {
    Field    string
    Operator string
    Value    interface{}
    Connector string // "AND", "OR"
}

func buildWhereFromConditions(conditions []Condition) sq.Sqlizer {
    var sqlizers []sq.Sqlizer
    
    for i, cond := range conditions {
        var sqlizer sq.Sqlizer
        
        switch cond.Operator {
        case "=":
            sqlizer = sq.Eq{cond.Field: cond.Value}
        case "!=":
            sqlizer = sq.NotEq{cond.Field: cond.Value}
        case ">":
            sqlizer = sq.Gt{cond.Field: cond.Value}
        case "<":
            sqlizer = sq.Lt{cond.Field: cond.Value}
        case "~":
            sqlizer = sq.Like{cond.Field: fmt.Sprintf("%%%s%%", cond.Value)}
        case "!~":
            sqlizer = sq.NotLike{cond.Field: fmt.Sprintf("%%%s%%", cond.Value)}
        }
        
        if i > 0 && cond.Connector == "OR" {
            sqlizers = append(sqlizers, sq.Or{
                sq.And(sqlizers...),
                sqlizer,
            })
            sqlizers = nil
        } else {
            sqlizers = append(sqlizers, sqlizer)
        }
    }
    
    return sq.And(sqlizers...)
}

6. 使用Expr处理复杂表达式

// 对于特别复杂的条件,可以使用Expr
where := sq.Expr(`
    (Bar.Alpha = ? AND Foo.Bar.X = ?) 
    OR (Foo.Bar.Beta > ? AND Alpha.Bar != ?)
`, 7, "hello", 21, "hello")

sql, args, _ := sq.Select("*").From("table").Where(where).ToSql()

squirrel的Sqlizer接口允许灵活组合条件,通过AndOrEqGt等方法可以构建任意复杂的WHERE条件。对于用户输入的解析,需要先将字符串解析为结构化的条件对象,然后使用squirrel的方法构建查询。

回到顶部