# 批量混合SQL操作 ### 批量混合SQL操作API 在了解批量混合SQL操作API前,请先了解一下Sql执行单元的定义 ### Sql执行单元定义 * 当sqls为string时候,则Sql执行单元为该字符串的内容 * 当sqlkeys为string时,则Sql执行单元为所对应的SqlMap配置项或SqlTemplate模板 * 当sqls为[]string或map[string]string时候,则Sql执行单元为相关元素的字符串内容 * 当sqlkeys为[]string或map[string]string时候,则Sql执行单元为以相关元素为key所对应的SqlMap配置项或SqlTemplate模板 * Sql执行单元的具体内容,必须以"select", "insert", "delete", "update", "create", "drop"为起始内容,但后续内容不会继续做检查,请合理定义Sql执行单元内容。当执行单元内容不是以上起始内容,则对应索引或key返回的结果集为nil,请注意对返回结果集的nil判断 * Sql执行单元并非单条Sql语句,当执行insert,delete,update,create,drop操作时候,可以为多条Sql语句,这里需要对应的数据库的SQL语法支持。如在一个执行单元批量执行多条Sql,返回结果集作为一组所有执行单元的大结果集中的一个元素,这个结果集的数据类型为map[string]interface{},只有2个键值对,一个键值对的key为LastInsertId,一个键值对的key为RowsAffected,请控制好执行粒度。另外,目前不是所有数据库都支持返回LastInsertId,目前还在设计更通用的API来实现所有数据库都能支持此功能。 * 当执行select操作时候,执行单元的Sql语句必须为一条,返回结果集作为一组所有执行单元的大结果集中的一个元素 * insert,delete,update,create,drop操作不能和select操作混合定义在同一个执行单元中 * 最后,Sql执行单元基于以上约定,请合理组织 ### Sqls(sqls, parmas...)方法说明: 1. sqls参数 * sqls参数数据类型为interface{}类型,但实际参数类型检查时,只支持string,[]string和map[string]string三中类型,使用其他类型均会返回参数类型错误。 * 使用string类型则为执行单条Sql执行单元(传送门:[Sql执行单元定义](#SQL)),Execute()方法返回的结果集数据类型为[][]map[string]interface{},只有1个元素。 * 使用[]string则Execute()方法为有序执行多条Sql执行单元,Execute()方法返回的结果集数据类型为[][]map[string]interface{}类型,结果集元素个数与sqls参数的元素个数相同,每个元素索引与返回结果集的索引一一对应。 * 使用map[string]string类型则Execute()方法为无序执行多条Sql执行单元,Execute()方法返回的结果集数据类型为map[string][]map[string]interface{},结果集map的key与返回结果集的key一一对应。 2. parmas...参数 * 可以接收0个参数或则1个参数,当所有执行单元都无需执行参数时候,可以不传此参数 * parmas参数数据类型为interface{},但实际参数类型检查时,只支持map[string]interface{},[]map[string]interface{}和map[string]map[string]interface{}三种类型,使用其他类型均会返回参数类型错误。 * 使用map[string]interface{}类型时候,sqls参数类型必须为string类型,即map[string]interface{}类型为单条Sql执行单元的参数。 * 使用[]map[string]interface{}类型时候,sqls参数类型可以为string类型,此时只有第一个元素[0]map[string]interface{}会被提取,之后的元素将不起任何作用。同时,sqls参数类型也可以为[]string类型,这种参数组合是最常用的组合形式之一,sqls参数的索引和parmas参数的索引一一对应。当某个索引所对应的Sql执行单元是无参数的时候,请将此索引的值设为nil,即parmas[i] = nil * 使用map[string]map[string]interface{}类型时,sqls参数类型必须为map[string]string类型,这种参数组合是最常用的组合形式之一,sqls参数的key和parmas参数的key一一对应。当某个key所对应的Sql执行单元是无参数的时候,请将此key的值设为nil,即parmas[key] = nil ### SqlMapsClient(sqlkeys, parmas...)方法说明: 1. sqlkeys参数 * sqlkeys参数数据类型为interface{}类型,但实际参数类型检查时,只支持string,[]string和map[string]string三中类型,使用其他类型均会返回参数类型错误。 * 使用string类型则为执行单条Sql执行单元(Sql执行单元定义),即在xorm种缓存的SqlMap中的key所对应的配置项,Execute()方法返回的结果集数据类型为[][]map[string]interface{},只有1个元素。 * 使用[]string则Execute()方法为有序执行多条Sql执行单元,Execute()方法返回的结果集数据类型为[][]map[string]interface{}类型,结果集元素个数与sqls参数的元素个数相同,sqlkeys的索引与返回结果集的索引一一对应,sqlkeys存储的是每个元素的值是xorm缓存的SqlMap的key * 使用map[string]string类型则Execute()方法为无序执行多条Sql执行单元,Execute()方法返回的结果集数据类型为map[string][]map[string]interface{},sqlkeys的key与返回结果集的key一一对应,sqlkeys存储的是每个键值对的值是xorm缓存的SqlMap的key 2. parmas...参数 * 可以接收0个参数或则1个参数,当所有执行单元都无需执行参数时候,可以不传此参数 * parmas参数数据类型为interface{},但实际参数类型检查时,只支持map[string]interface{},[]map[string]interface{}和map[string]map[string]interface{}三种类型,使用其他类型均会返回参数类型错误。 * 使用map[string]interface{}类型时候,sqlkeys参数类型必须为string类型,即map[string]interface{}类型为单条Sql执行单元的参数。效果等同SqlMapClient()方法(请注意本方法名为SqlMapsClient)。 * 使用[]map[string]interface{}类型时候,sqlkeys参数类型支持两种: * 第1种为string类型,此时只有第一个元素[0]map[string]interface{}会被提取,之后的元素将不起任何作用。 * 第2种为[]string类型,这种参数组合是最常用的组合形式之一,sqlkeys参数的索引和parmas参数的索引一一对应。当某个索引所对应的Sql执行单元是无参数的时候,请将此索引的值设为nil,即parmas[i] = nil * 使用map[string]map[string]interface{}类型时,sqlkeys参数类型必须为map[string]string类型,这种参数组合是最常用的组合形式之一,sqlkeys参数的key和parmas参数的key一一对应。当某个key所对应的Sql执行单元是无参数的时候,请将此key的值设为nil,即parmas[key] = nil ### SqlTemplatesClient(sqlkeys, parmas...)方法说明: 1. sqlkeys参数 * sqlkeys参数数据类型为interface{}类型,但实际参数类型检查时,只支持string,[]string和map[string]string三中类型,使用其他类型均会返回参数类型错误。 * 使用string类型则为执行单条Sql执行单元(Sql执行单元定义),即在xorm缓存的SqlTemplate中的key所对应的模板,Execute()方法返回的结果集数据类型为[][]map[string]interface{},只有1个元素。 * 使用[]string则Execute()方法为有序执行多条Sql执行单元,Execute()方法返回的结果集数据类型为[][]map[string]interface{}类型,结果集元素个数与sqls参数的元素个数相同,sqlkeys的索引与返回结果集的索引一一对应,sqlkeys存储的是每个元素的值是xorm缓存的SqlTemplate的key * 使用map[string]string类型则Execute()方法为无序执行多条Sql执行单元,Execute()方法返回的结果集数据类型为map[string][]map[string]interface{},sqlkeys的key与返回结果集的key一一对应,sqlkeys存储的是每个键值对的值是xorm缓存的SqlTemplate的key 2. parmas...参数 * 可以接收0个参数或则1个参数,当所有执行单元都无需执行参数时候,可以不传此参数 * parmas参数数据类型为interface{},但实际参数类型检查时,只支持map[string]interface{},[]map[string]interface{}和map[string]map[string]interface{}三种类型,使用其他类型均会返回参数类型错误。 * 使用map[string]interface{}类型时候,sqlkeys参数类型必须为string类型,即map[string]interface{}类型为单条Sql执行单元的参数。效果等同SqlMapClient()方法(请注意本方法名为SqlMapsClient)。 * 使用[]map[string]interface{}类型时候,sqlkeys参数类型支持两种: * 第1种为string类型,此时只有第一个元素[0]map[string]interface{}会被提取,之后的元素将不起任何作用; * 第2种为[]string类型,这种参数组合是最常用的组合形式之一,sqlkeys参数的索引和parmas参数的索引一一对应。当某个索引所对应的Sql执行单元是无参数的时候,请将此索引的值设为nil,即parmas[i] = nil * 使用map[string]map[string]interface{}类型时,sqlkeys参数类型必须为map[string]string类型,这种参数组合是最常用的组合形式之一,sqlkeys参数的key和parmas参数的key一一对应。当某个key所对应的Sql执行单元是无参数的时候,请将此key的值设为nil,即parmas[key] = nil ### Execute()方法说明: * 一共3个返回值,([][]map[string]interface{}, map[string][]map[string]interface{}, error) * 当以上3个方法的sqls或sqlkeys参数为string或[]string时为有序执行Sql执行单元,故返回结果集为第一个返回值,Slice存储,第二返回值为nil * 当以上3个方法的sqls或sqlkeys参数为map[string]string时为无序执行Sql执行单元,返回结果集为第二个返回值,map存储,第一个返回值为nil * 当以上3个方法执行中出现错误,则第三个返回值有值,前2个返回值均为nil <a name="SQL"></a> ~~~ //第一种方式,可以从Engine对象轻松进行使用,该方式自动管理事务,注意如果您使用的是mysql,数据库引擎为innodb事务才有效,myisam引擎是不支持事务的。 engine.Sqls(sqls, parmas...).Execute() engine.SqlMapsClient(sqlkeys, parmas...).Execute() engine.SqlTemplatesClient(sqlkeys, parmas...).Execute() //第2种方式,手动创建Session对象进行调用,该方式需要您手动管理事务 session := engine.NewSession() defer session.Close() // add Begin() before any action tx,err := session.BeginTrans() _, err = tx.Session().Exec("delete from userinfo where username = ?", user2.Username) if err != nil { tx.RollbackTrans() return } //Execuet返回值有3个,分别为slice,map,error类型 results, _, err = tx.Session().Sqls(sqls, parmas...).Execute() if err != nil { tx.RollbackTrans() return } _, results, err = tx.Session().SqlMapsClient(sqlkeys, parmas...).Execute() if err != nil { tx.RollbackTrans() return } results, _, err = tx.Session().SqlTemplatesClient(sqlkeys, parmas...).Execute() if err != nil { tx.RollbackTrans() return } // add Commit() after all actions err = tx.CommitTrans() if err != nil { return } //支持两种返回结果集 //Slice形式类似如下 /* [ [ { "id": "6", "name": "xorm" }, { "id": "7", "name": "xormplus" }, { "id": "8", "name": "ibatis" } ], [ { "LastInsertId": 0, "RowsAffected": 0 } ], [ { "LastInsertId": 0, "RowsAffected": 0 } ], [ { "LastInsertId": 13, "RowsAffected": 1 } ] ] */ //Map形式类似如下 /* { "deleteUser": [ { "LastInsertId": 0, "RowsAffected": 0 } ], "insertUser": [ { "LastInsertId": 11, "RowsAffected": 1 } ], "updateUser": [ { "LastInsertId": 0, "RowsAffected": 0 } ], "userList": [ { "id": "3", "name": "xorm" }, { "id": "4", "name": "xormplus" }, ] } */ ~~~