I have a function which calls a stored procedure with providing its parameters.
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;
}
and the stored procedure;
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:UsersLethAppDataLocalTemp~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
The problem is when the stored procedure is called it passes the value of sClanID to bRet which is something I found by executing the statement directly on the SQL server (2008 R2) because when I directly executing like;
exec CREATE_KNIGHTS 15001, 2, 1, "OpenKO", 'test'
it tries to convert char (OpenKO) to tinyint, and if I give a number as strName instead of OpenKO, it says procedure expects a parameter to @strChief, which was not supplied.
I have other functions with the same structure and they are perfectly fine in the manner of taking parameters correctly and returning the output but why does it not ? and How can I solve this ?
If you like you can see the whole project on github
For SEO to this question, as I mentioned below, If I enter the sClanID as words, it gives the error “Error converting data type char to tinyint” and if I enter numbers, it gives “expects parameter @statement, which was not supplied”
2
Answers
Although I managed to solve my question, I won't accept my own answer since I'm looking an answer according to its cause.
I solved it by just giving the first parameter as bRet to the ODBC command, so the last version of the code was;
Since, the problem caused because there was a parameter shift while passing the values to the SP, just passing a initial value the OUTPUT variable solved the problem.
The best practice is putting OUTPUT parameters declaration always at the end, and call SP with parameter names.
The following statement should change like that;
And the code should be like this;