如何使用c++通过ADO调用mysql有参存储过程并获取结果集 80C

先放代码,遇到的问题是 调用mysql**有参**存储过程时获取不到结果集

#include <iostream>
#include <atlstr.h>

#import "MSADO15.DLL" rename_namespace("ADOCG") rename("EOF","EndOfFile")
using namespace ADOCG;

using namespace std;

int main() {
    try
    {
        HRESULT hr = CoInitialize(NULL);

        assert(SUCCEEDED(hr));//返回值可判断初始化COM是否成功,请用SUCCEEDED来判断

        _CommandPtr                     m_DBCommand;                        //命令对象
        _RecordsetPtr                   m_DBRecordset;                      //记录对象
        _ConnectionPtr                  m_DBConnection;                     //数据对象

        //创建对象
        m_DBCommand.CreateInstance(__uuidof(Command));
        m_DBRecordset.CreateInstance(__uuidof(Recordset));
        m_DBConnection.CreateInstance(__uuidof(Connection));

        //效验数据
        if (m_DBCommand == NULL) throw TEXT("创建 m_DBCommand 对象失败");
        if (m_DBRecordset == NULL) throw TEXT("创建 m_DBRecordset 对象失败");
        if (m_DBConnection == NULL) throw TEXT("创建 m_DBConnection 对象失败");

        CString m_strConnect;

        //构造连接
        m_strConnect.Format(TEXT("Driver={MySQL ODBC 8.0 Unicode Driver};UID=%s;PWD=%s;DataBase=%s;Persist Security Info=True;Server=%s;Port=%d;Option=3"),
            "hhh", "123456", "Test", "192.168.1.115", 3306);

        //打开连接
        m_DBConnection->Open(_bstr_t(m_strConnect), L"", L"", adConnectUnspecified);

        m_DBConnection->CursorLocation = adUseClient;
        m_DBCommand->ActiveConnection = m_DBConnection;

        assert(SUCCEEDED(hr));//返回值可判断初始化COM是否成功,请用SUCCEEDED来判断

        LONG lParameterCount = m_DBCommand->Parameters->Count;
        if (lParameterCount > 0L)
        {
            for (LONG i = lParameterCount; i > 0; i--)
            {
                m_DBCommand->Parameters->Delete(i - 1);
            }
        }

        //添加参数
        _ParameterPtr Parameter;
        Parameter = m_DBCommand->CreateParameter("wServerID", adInteger, adParamInput, sizeof(LONG), _variant_t((LONG)0));
        m_DBCommand->Parameters->Append(Parameter);
        Parameter = m_DBCommand->CreateParameter("wMachineID", adInteger, adParamInput, sizeof(LONG), _variant_t((LONG)0));
        m_DBCommand->Parameters->Append(Parameter);


        m_DBCommand->CommandText = "LoadGameRoomItem2";
        m_DBCommand->CommandType = adCmdText;

        m_DBRecordset = m_DBCommand->Execute(NULL, NULL, adCmdStoredProc);

        long RecordCount = m_DBRecordset->GetRecordCount();

        cout << RecordCount << endl;

        _variant_t DBVarValue;
        if (m_DBRecordset->EndOfFile != VARIANT_TRUE)
        {
            FieldsPtr RecordFields = m_DBRecordset->GetFields();
            DBVarValue = RecordFields->GetItem("ServerID")->GetValue();
            WORD wValue = DBVarValue;
        }
    }
    catch (_com_error& ComError)
    {

        cout << ComError.Description() << endl;
    }
    return 0;
}

储存过程如下

CREATE DEFINER=`root`@`%` PROCEDURE `LoadGameRoomItem2`(
in wServerID INT,                
in wMachineID INT   
)
BEGIN
SELECT * from gameroominfo;
END

目前遇到的问题就是,怎么也获取不到结果集,RecordCount始终为零(强行读取提示“BOF 或 EOF 中有一个是“真”,或者当前的记录已被删除,所需的操作要求一个当前的记录。”并不是 显示没有其实有,而是确实没有结果集),但是如果我将参数去掉

        //添加参数
//      _ParameterPtr Parameter;
//      Parameter = m_DBCommand->CreateParameter("wServerID", adInteger, adParamInput, sizeof(LONG), _variant_t((LONG)0));
//      m_DBCommand->Parameters->Append(Parameter);
//      Parameter = m_DBCommand->CreateParameter("wMachineID", adInteger, adParamInput, sizeof(LONG), _variant_t((LONG)0));
//      m_DBCommand->Parameters->Append(Parameter);


CREATE DEFINER=`root`@`%` PROCEDURE `LoadGameRoomItem2`(
)
BEGIN
SELECT * from gameroominfo;
END

那么则可以获得结果集(RecordCount数量为40,if (m_DBRecordset->EndOfFile != VARIANT_TRUE)判断能进去,ServerID也能读取到),我试过在存储过程前面后面分别加一个update判断过是不是存储过程没执行成功,但是不管有参无参存储过程,两个Updata都走到了,而且不管有参无参直接在数据库调用都是有结果集的

数据库日志如下

190923 15:32:38  
         7534 Connect   hhh@DESKTOP-989OGGH on Test
         7534 Query SET NAMES utf8
         7534 Query SET character_set_results = NULL
         7534 Query SET SQL_AUTO_IS_NULL = 0
         7534 Query select database()
         7534 Query select database()
         7534 Query SELECT @@tx_isolation
         7534 Query set @@sql_select_limit=DEFAULT
         7534 Query call LoadGameRoomItem2
         7534 Quit  

190923 15:47:54 
         7621 Connect   hhh@DESKTOP-989OGGH on Test
         7621 Query SET NAMES utf8
         7621 Query SET character_set_results = NULL
         7621 Query SET SQL_AUTO_IS_NULL = 0
         7621 Query select database()
         7621 Query select database()
         7621 Query SELECT @@tx_isolation
         7621 Prepare   call LoadGameRoomItem2(?, ?)
         7621 Query set @@sql_select_limit=DEFAULT
         7621 Execute   call LoadGameRoomItem2('0', '0')
         7621 Close stmt    
         7621 Quit  

困扰小弟好几天了,希望各位神仙大佬能帮帮小弟T_T

----------------------------------编辑分界线--------------------------------
图片说明图片说明
如图,是要像这样处理一张表的内容的,单单用output参数是做不到的,主要问题在如果不加参数这些东西是可以读出来的,但是加了参数就获取不到结果集了。。。。

2个回答

在navicat里面测试下,用exec调用,看看行不行
检查下你的连接参数

我用这个代码,绝对可以

// AccessSqlserverByAdo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;

#import "C:\Program Files\Common Files\System\ado\msado15.dll" rename("EOF", "adoEOF") rename("BOF", "adoBOF")
using namespace ADODB;

int _tmain(int argc, _TCHAR* argv[])
{
    ::CoInitialize(NULL);   
    _ConnectionPtr m_pConnection=NULL;  

    m_pConnection.CreateInstance(__uuidof(Connection));  



    _bstr_t strConnect = "Provider=SQLOLEDB.1;Password=1111111;Persist Security Info=True; \
                         User ID=sa;Initial Catalog=SoftwareVerification;Data Source=112.74.105.204"; 


    //下面代码执行一个查询
    /*
    try
    {
        _RecordsetPtr m_pRecordset=NULL;  
     m_pRecordset.CreateInstance(__uuidof(Recordset));
        m_pConnection->Open(strConnect,"","",adModeUnknown);
        _variant_t vAffected;
        _bstr_t bstrSql("select user_name,user_password from userssss");
        m_pRecordset = m_pConnection->Execute(bstrSql,&vAffected,adCmdText);
        while(!m_pRecordset->adoBOF)
        {
            _variant_t UserName = m_pRecordset->GetCollect(_variant_t((long)0));
            _variant_t PassWord = m_pRecordset->GetCollect("user_password");
            if(UserName.vt != NULL)
            {
                cout<<(LPCSTR)(_bstr_t)UserName<<"   "<<(LPCSTR)(_bstr_t)PassWord<<endl;
            }
            m_pRecordset->MoveNext();
        }
        m_pRecordset->Close();
        m_pConnection->Close();
    }
    catch(_com_error e)
    {
        wcout<<e.Description()<<endl;
    }
    */

    //调用存储过程
        try
    {
        m_pConnection->Open(strConnect,"","",adModeUnknown);
        _CommandPtr cmmd;
        HRESULT hr = cmmd.CreateInstance(__uuidof(Command));

        cmmd->Parameters->Append(cmmd->CreateParameter(_bstr_t("Return"),adInteger,adParamReturnValue,4));
        cmmd->Parameters->Append(cmmd->CreateParameter(_bstr_t("strUserName"),adVarChar,adParamInput,50,"zds"));
        cmmd->Parameters->Append(cmmd->CreateParameter(_bstr_t("strPassWord"),adVarChar,adParamInput,50,"111"));
        cmmd->Parameters->Append(cmmd->CreateParameter(_bstr_t("nSoftWareID"),adInteger,adParamInput,4,"1"));
        cmmd->Parameters->Append(cmmd->CreateParameter(_bstr_t("strMsg"),adVarChar,adParamOutput,50));


        cmmd->CommandText = _bstr_t("UserLogin");
        cmmd->ActiveConnection = m_pConnection;
        cmmd->CommandType = adCmdStoredProc;
        cmmd->Execute(NULL,NULL,adCmdStoredProc);
        string strRet = (const char*)(_bstr_t)cmmd->Parameters->GetItem("strMsg")->GetValue();
        int nRet = cmmd->Parameters->GetItem("Return")->GetValue();
        cout<<strRet<<endl;
    }
    catch(_com_error e)
    {
        wcout<<e.Description()<<endl;
    }

    ::CoUninitialize();
    return 0;
}

满意请采纳,采纳后可追问

qq_33371768
笑眯眯哦 话说,你用的是sqlserver,我的是Mysql,我之前用的就是Sqlserver,没遇到过这个问题,现在的公司用的是Mysql= =
4 个月之前 回复
qq_33371768
笑眯眯哦 我用navicat测试过的(直接复制的SQL生成的日志测试的),有参无参的结果都一样(毕竟储存过程实现里面完全没用到参数,也不可能不一样)但是不加参数就可以获取到记录集,加了参数就获取不到
4 个月之前 回复
qq_33371768
笑眯眯哦 是这样的,我想返回一个记录集,也就是一张表,而不是单单一个参数,单单一个参数确实没问题。。。
4 个月之前 回复

是不是你CreateParameter的wMachineID和存储过程里的变量名strMachineID不一致?

infoworld
infoworld 回复笑眯眯哦: 你的参数只是0吧,试过传入非0的整型吗?再看看日志能否正确输出. 如果能正确输出,那就可能是存储过程参数作为select的参数类型有问题. 你试下在存储过程里打印参数的类型.
4 个月之前 回复
qq_33371768
笑眯眯哦 回复infoworld: 而且我还试过用参数来UPDATA表,包括字符串和INT都是可以把我给的参数赋值到表里,参数是没问题的
4 个月之前 回复
qq_33371768
笑眯眯哦 回复infoworld: 和这个没关系的,因为你看SQL日志里面,7621 Execute call LoadGameRoomItem2('0', '0'),调用都已经完成了,而且我存储过程里面完全没有对于参数的处理,只是单纯select了一下,我直接复制日志里面的调用语句自己调用是可以获取结果集的,参数问题应该在日志里可以看到的
4 个月之前 回复
infoworld
infoworld 回复笑眯眯哦: 会不会是你的存储过程参数变量类型声明的INT,而C++编码输入的LONG类型。还有你可以试下存储过程只有一个参数的情况下验证.
4 个月之前 回复
qq_33371768
笑眯眯哦 没,我打错了=.=我写的时候是用的str变量,想减少干扰因素,就改成INT了,没改全,我编辑一下
4 个月之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问