Golang MySQL存储过程的使用

前端之家收集整理的这篇文章主要介绍了Golang MySQL存储过程的使用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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 //

Go调用存储过程代码,亲测可用

@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
}

todo 完善该wiki

猜你在找的Go相关文章