Golang MysqL存储过程的使用
使用前阅读
ref-1:问题来源 [支付系统数据库设计的关键问题 ]
ref-2:[Golang 用go-sql-driver 调用MySQL存储过程时的问题排查]
编辑文件src/github.com/go-sql-driver/MysqL/packets.go文件,在函数writeAuthPacket(cipher []byte) (大约在210行)的客户端标志位处添加下面两个标志:
@H_502_10@func (mc *MysqLConn) writeAuthPacket(cipher []byte) error {
// Adjust client flags based on server support
clientFlags := clientProtocol41 |
clientSecureConn |
clientLongPassword |
clientTransactions |
clientLocalFiles |
**clientMultiStatements | // 添加这行
clientMultiResults |** //再添加这行
mc.flags&clientLongFlag
@H_502_10@if mc.cfg.clientFoundRows {
clientFlags |= clientFoundRows
}
一、MysqL创建存储过程
-- 单行执行以下语句
@H_502_10@SET NAMES utf8;
-- dsp_settle数据库
USE dsp_settle;
DROP @H_502_10@PROCEDURE IF EXISTS settle_balance_deduction;
-- [1]设置分隔符为//
DELIMITER //
--[2] 执行source /path/@H_502_10@to/@H_502_10@procedure.sql; !!! ERROR
--[2]@H_502_10@copy /PATH/@H_502_10@TO/@H_502_10@procedure.sql to console and enter --[3]还原分隔符 DELIMITER ;
--[4]调用示例
call settle_balance_deduction(5372539,1234,100,@out_status);
@H_502_10@select @out_status;
-- 其他常用操作
-- 调研存储过程
call procedure_name(parameters);
-- 查询存储过程
SHOW @H_502_10@PROCEDURE STATUS;
-- 显示一个存储过程详情
SHOW @H_502_10@CREATE @H_502_10@PROCEDURE procedure_name;
-- 删除存储过程
DROP @H_502_10@PROCEDURE procedure_name;
存储过程代码
-- 创建存储过程
CREATE PROCEDURE settle_balance_deduction (in_userID bigint,in_planID INT,in_money INT,OUT out_status INT )
BEGIN
-- 变量 用户实际余额
DECLARE account_balance INT;
START TRANSACTION;
SELECT balance INTO account_balance FROM dsp_settle.user_balance WHERE userId = in_userID AND status = 0 AND isDelete = 0 FOR UPDATE;
IF account_balance >= in_money THEN
-- 扣费操作
UPDATE user_balance SET balance = balance - in_money,opUserId = 1001 WHERE userId = in_userID;
-- 扣费记录
INSERT INTO dsp_settle.charge_record(userId,planId,charge,opUserId,addTime) VALUES (in_userID,in_planID,in_money, 1001,NOW());
-- 提交事务处理
COMMIT;
-- 返回结果状态1
SET out_status = 1;
ELSE
-- 余额小于扣费额,不操作
ROLLBACK;
-- 返回结果状态0
SET out_status = 0;
END IF;
END //
@H_502_10@package balance
@H_502_10@import (
"database/sql"
_ "github.com/go-sql-driver/MysqL"
"strconv"
"fmt"
)
@H_502_10@const (
//DSN = "root:tongzhen@tcp(127.0.0.1:3306)"
DSN = "root:123456@tcp(10.48.23.51:8086)"
DB_DSP = "dsp"
DB_SETTLE = "dsp_settle"
)
//扣费结算
@H_502_10@func Settle(userID int,planID int,charge int) int{
db,err := sql.Open("MysqL",DSN + "/" + DB_SETTLE)
@H_502_10@if err != nil {
panic(err.Error())
}
@H_502_10@defer db.Close()
handle,err := db.Prepare("CALL dsp_settle.settle_balance_deduction(?,?,@out_status)")
@H_502_10@if err != nil {
panic(err.Error())
}
@H_502_10@defer handle.Close()
//call procedure
@H_502_10@var result sql.Result
result,err = handle.Exec(userID,planID,charge)
@H_502_10@if err != nil {
panic(err.Error())
}
fmt.Println(result)
@H_502_10@var sql string = "SELECT @out_status as ret_status"
selectInstance,err := db.Prepare(sql)
@H_502_10@if err != nil {
panic(err.Error())
}
@H_502_10@defer selectInstance.Close()
@H_502_10@var ret_status int
err = selectInstance.QueryRow().Scan(&ret_status)
@H_502_10@if err != nil {
panic(err.Error())
}
fmt.Println(ret_status)
@H_502_10@return ret_status
}