zoukankan      html  css  js  c++  java
  • Golang数据库操纵对IN语句的支持

    一:

    在实际的工程项目中,SQL通常使用预编译的形式进行执行操纵,可以有效的防止SQL注入的风险,提高编码的规范性。
    golang中使用sqlx进行sql查询的时候,在使用in语句在一个集合中查询的时候,若使用预编译形式则通常有两种形式:
    方法一:
    使用语言的for语句循环生成SQL语句中的“?”,类似这样:

    list:=[]int{1,2,4,66}
    sql:="select * from books where book_id IN (%s)"
    inStatus:=""
    params:=make([]interface{},0)
    for i:=0;i<len(list);i++{
        if i==0{
            inStatus+="?"
        }else{
            inStatus+=",?"
        }
        params=append(params , list[i])
    }
    sql = fmt.Sprintf(sql ,inStatus )
    db.Exec(sql , params...)

    方法二:
    其实sqlx内置了一个In()方法用于处理这种情况,可以使得对in的处理十分优雅。
    其实该方法的实现和我们方法一的处理原理类似。

    // In expands slice values in args, returning the modified query string
    // and a new arg list that can be executed by a database. The `query` should
    // use the `?` bindVar.  The return value uses the `?` bindVar.
    
    func In(query string, args ...interface{}) (string, []interface{}, error) 

    输入的参数query是一个sql语句,其中的需要使用In list的地方使用(?)代替,args为按照前后顺序的查询参数,按照实际对应?的次序的若干个参数。返回值有三个:
    第一个,string,是处理完后的sql语句,其中的In查询语句中的一个?已经按照实际的list长度进行处理,替换为多个“?”
    第二个,[]interface{},查询参数列表,
    第三个,error,错误对象

    bookList:=make([]Book , 0)
    sql := "SELECT * FROM books where book_id IN (?) AND status != ? ORDER BY create_time DESC"
    ids:=[]int{122,211,110}
    sql, args, err := sqlx.In(sql, ids, model.StatusSelfDeleted) //model.StatusSelfDeleted="DELETED"
    if err != nil {
        return bookList
    }
    err = db.Select(&bookList, sql, args...) //db为*sqlx.DB类型

    其中sqlx.In函数返回的sql如下:

    SELECT * FROM books where book_id IN (?,?,?) AND status != ? ORDER BY create_time DESC 

    args为:

    [122,211,110,"DELETED"]

    二:

    如果的数组中有两个int,构建它:

    SELECT some_column
    FROM table_name
    WHERE id IN (?, ?)

    如果你有四个,构建:

    SELECT some_column
    FROM table_name
    WHERE id IN (?, ?, ?, ?)

    等等。你需要的是一个简单的函数,可以产生n占位符; 有很多方法可以做到这一点:

    func placeholders(n int) string {
        ps := make([]string, n)
        for i := 0; i < n; i++ {
            ps[i] = "?"
        }
        return strings.Join(ps, ",")
    }

    或者:

    func placeholders(n int) string {
        var b strings.Builder
        for i := 0; i < n - 1; i++ {
            b.WriteString("?,")
        }
        if n > 0 {
            b.WriteString("?")
        }
        return b.String()
    }
    uery := fmt.Sprintf("select some_column from table_name where id in (%s)", placeholders(len(idsToGet)))
    rows, err := db.Query(query, idsToGet...)
  • 相关阅读:
    程序跳过UAC研究及实现思路(两种方法,现在可能都不行了)
    getch(),getche(),getchar()的区别
    命令行版扫雷(vc08)
    类成员函数指针的特殊之处(成员函数指针不是指针,内含一个结构体,需要存储更多的信息才能知道自己是否virtual函数)
    WCF与Web API 区别
    扩展方法库
    开源Dubbox
    AngularJs应用页面
    浅谈可扩展性框架:MEF
    AngularJs + ASP.NET MVC
  • 原文地址:https://www.cnblogs.com/sunlong88/p/12003400.html
Copyright © 2011-2022 走看看