c++ - 为什么 SQL Server 将值传递给存储过程中的 OUTPUT 变量?

标签 c++ sql-server tsql stored-procedures odbc

我有一个调用存储过程并提供其参数的函数。

int8 CDBAgent::CreateKnights(uint16 sClanID, uint8 bNation, string & strKnightsName, string & strChief, uint8 bFlag)
{
    int8 bRet = -1;
    unique_ptr<OdbcCommand> dbCommand(m_GameDB->CreateCommand());
    if (dbCommand.get() == nullptr)
        return bRet;


    dbCommand->AddParameter(SQL_PARAM_OUTPUT, &bRet);
    dbCommand->AddParameter(SQL_PARAM_INPUT, strKnightsName.c_str(), strKnightsName.length());
    dbCommand->AddParameter(SQL_PARAM_INPUT, strChief.c_str(), strChief.length());

    if (!dbCommand->Execute(string_format(_T("{? = CALL CREATE_KNIGHTS ( %d, %d, %d, ?, ?)}"), sClanID, bNation, bFlag)))
        ReportSQLError(m_GameDB->GetError());


    return bRet;
}

和存储过程;

USE [KN_online]
GO
/****** Object:  StoredProcedure [dbo].[CREATE_KNIGHTS]    Script Date: 09/04/2016 03:09:46 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
-- Batch submitted through debugger: SQLQuery4.sql|7|0|C:\Users\Leth\AppData\Local\Temp\~vs3286.sql

/****** Object:  Stored Procedure dbo.CREATE_KNIGHTS    Script Date: 6/6/2006 6:03:32 PM ******/

-- modify by sungyong 2002.09.27

ALTER PROCEDURE [dbo].[CREATE_KNIGHTS]
@nRet       smallint OUTPUT,
@index      smallint,
@nation     tinyint,
@community  tinyint,
@strName    char(21), 
@strChief   char(21)


AS

DECLARE @Row tinyint, @knightsindex smallint, @knightsname char(21)
    SET @Row = 0    SET @knightsindex = 0  SET @knightsname = ''

    SELECT @Row = COUNT(*) FROM KNIGHTS WHERE IDNum = @index or  IDName = @strName

    IF @Row > 0 or @index = 0
    BEGIN
        SET @nRet =  3
        RETURN
    END

    --SELECT @Row = COUNT(*) FROM KNIGHTS WHERE IDName = @strName

    --IF @Row > 0
--  BEGIN
    --  SET @nRet =  3
        --RETURN
--  END

BEGIN TRAN  

    INSERT INTO KNIGHTS ( IDNum, Nation, Flag, IDName, Chief  ) 
    VALUES   (@index, @nation, @community, @strName, @strChief )

    INSERT INTO KNIGHTS_USER ( sIDNum, strUserID  ) 
    VALUES   (@index,  @strChief )

    IF @@ERROR <> 0
    BEGIN    
        ROLLBACK TRAN 
        SET @nRet =  6
        RETURN
    END

--  UPDATE USERDATA SET Knights = @index, Fame = 1 WHERE strUserId = @strChief  -- 1 == Chief Authority

    IF @@ERROR <> 0
    BEGIN    
        ROLLBACK TRAN 
        SET @nRet =  6
        RETURN
    END

COMMIT TRAN
SET @nRet =  0

问题是当调用存储过程时,它会将 sClanID 的值传递给 bRet,这是我通过直接在 SQL Server (2008 R2) 上执行语句发现的,因为当我直接执行 like;

exec CREATE_KNIGHTS 15001, 2, 1, "OpenKO", 'test'

它尝试将 char (OpenKO) 转换为 tinyint,如果我给出一个数字作为 strName 而不是 OpenKO,它说过程需要一个参数给 @strChief,但没有提供。

我有其他具有相同结构的函数,它们在正确获取参数和返回输出方面非常好,但为什么不呢?我该如何解决这个问题?

如果您愿意,可以在 github 上查看整个项目

对于这个问题的 SEO,正如我在下面提到的,如果我输入 sClanID 作为单词,它会给出错误“Error converting data type char to tinyint”,如果我输入数字,它会给出“expects parameter @statement, which未提供”

最佳答案

最佳做法是始终将 OUTPUT 参数声明放在末尾,并使用参数名称调用 SP。

ALTER PROCEDURE [dbo].[CREATE_KNIGHTS]
@index      smallint,
@nation     tinyint,
@community  tinyint,
@strName    char(21), 
@strChief   char(21),
@nRet       smallint OUTPUT

下面的语句应该这样改;

if (!dbCommand->Execute(string_format(_T("{CALL CREATE_KNIGHTS ( %d, %d, %d, ?, ?, ?)}"), sClanID, bNation, bFlag)))

代码应该是这样的;

    dbCommand->AddParameter(SQL_PARAM_INPUT, strKnightsName.c_str(), strKnightsName.length());
    dbCommand->AddParameter(SQL_PARAM_INPUT, strChief.c_str(), strChief.length());
    dbCommand->AddParameter(SQL_PARAM_OUTPUT, &bRet);

关于c++ - 为什么 SQL Server 将值传递给存储过程中的 OUTPUT 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39316439/

相关文章:

android - 将 cout 格式的数据写入 printf

c++ - Pimpl 成语 vs 纯虚拟类接口(interface)

sql - 将日期时间变量的时间部分设置为 18 :00

sql-server - SSRS 2008 - 如何向矩阵添加小计

sql - 无法直接转换为十进制值?

c++ - Qt。忽略另一个小部件中的任何鼠标事件

iphone - 来自 const void* 错误的无效转换

sql-server - SQL Server 2005性能问题

sql-server - SQL select join 帮助

sql-server - 删除系统版本化时态表的过程