go mysql sqlx 使用存储过程且返回多结果解决办法,多参数输出替代方法

2 篇文章 0 订阅

环境:

Golang语言下使用封装sqlx 执行mysql的存储过程语句。
存储过程借用网上例子,作用是实现通用分页效果,同时返回总页数和总行数

历程:

  • 存储过程代码
/*执行例子"
CALL sp_viewPage(
'*'#查询字段
,'userupdatelog'#表名
,'1=1'#条件
,'Id desc'#排序
,1 #页码
,20 #每页记录数
,@totalcount #输出总记录数
,@pagecount #输出用页数
);
SELECT @totalcount,@pagecount;
*/

DROP PROCEDURE IF EXISTS `sp_viewPage`;

CREATE PROCEDURE sp_viewPage(
_fields VARCHAR(1000), #要查询的字段,用逗号(,)分隔
_tables TEXT, #要查询的表
_where VARCHAR(2000), #查询条件
_orderby VARCHAR(200), #排序规则
_pageindex INT, #查询页码
_pageSize INT, #每页记录数
/*_sumfields VARCHAR(200),#求和字段 */
#输出参数
OUT _totalcount INT, #总记录数
OUT _pagecount INT #总页数
/* OUT _sumResult VARCHAR(2000)#求和结果 */
)
BEGIN
#140529-xxj-分页存储过程
#计算起始行号
SET @startRow = _pageSize * (_pageIndex - 1);
SET @pageSize = _pageSize;
SET @rowindex = 0; #行号

#合并字符串
SET @strsql = CONCAT(
#'select sql_calc_found_rows @rowindex:=@rowindex+1 as rownumber,' #记录行号
'select sql_calc_found_rows '
,_fields
,' from '
,_tables
,CASE IFNULL(_where, '') WHEN '' THEN '' ELSE CONCAT(' where ', _where) END
,CASE IFNULL(_orderby, '') WHEN '' THEN '' ELSE CONCAT(' order by ', _orderby) END
,' limit '
,@startRow
,','
,@pageSize
);

PREPARE strsql FROM @strsql;#定义预处理语句
EXECUTE strsql; #执行预处理语句
DEALLOCATE PREPARE strsql; #删除定义
#通过 sql_calc_found_rows 记录没有使用 limit 语句的记录,使用 found_rows() 获取行数
SET _totalcount = FOUND_ROWS();

#计算总页数
IF (_totalcount <= _pageSize) THEN
SET _pagecount = 1;
ELSE IF (_totalcount % _pageSize > 0) THEN
SET _pagecount = _totalcount DIV _pageSize + 1;
ELSE
SET _pagecount = _totalcount DIV _pageSize;
END IF;
END IF;
SELECT _totalcount,_pagecount;
END

此语句包含两个输出,一个是详细行数的内容,另一个是总行数和总页数。
则包含两个结果表

  • go实现
package sqls

import "fmt"
import "testing"

func TestConn(t *testing.T) {
	fmt.Print("hello")
	con := new(Conninf)//这是我自定义的数据结构,实现将连接信息放在另一个页面。
	database := con.Conn()
	if database != nil {
		var totalcount, pagecount = 0, 0
		rows, querr := database.Queryx("CALL sp_viewPage('id,name','customer','1=1','Id desc',1 ,20 ,@page ,@totalcount)")
		//此处执行存储过程使用Queryx方法。但是Query应该也可以。customer是我的自定义表
		var idx int
		var name = ""
		if querr != nil {
			fmt.Printf("query database failed, err:%v", querr)
			return
		} //查询数据库出错
		for rows.Next() {//先使用Next方法
			if scanerr := rows.Scan(&idx, &name); scanerr != nil {
				fmt.Printf("scan failed, err:%v", scanerr)
				return
			} //获取单条数据
			fmt.Println(idx)
			fmt.Println(name)
		}
		///关键
		if rows.NextResultSet() {//再使用NextResultSet方法跳转到下一个表
			for rows.Next() {//此处Next方法不可省略,否则报错
				if scanerr := rows.Scan(&pagecount, &totalcount); scanerr != nil {
					fmt.Printf("scan failed, err:%v", scanerr)
					return
				}
			}
			fmt.Println(pagecount)
			fmt.Println(totalcount)
		}
	}
}

结果:

实现方法关键在于存储过程使用多结果输出,最后在Go上使用NextResultSet()方法来跳转。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值