I tried to invoke MS SQL Server stored procedure via ODBC. I wanted to both send data-at-execution and get an output parameter. When the data was send by SQLPutData the return value was unavailable
create procedure AddImage @pvchName varchar(80), @pData image, @pnID integer output
C code: //*********************************************************** long CBergenStoredProcs::AddImage( LPCSTR/*[80]*/ pvchName, CLongBinary *pData, long *pnID) { long lnRetVal, lnStrLen_or_IndPtr[4]; SQLRETURN lSQLres = SQL_SUCCESS; int lcbParamSize;
EnsureStmt(); DBTRY(SQLPrepare(m_hstmt, SQL_TEXT("{?=call AddImage(?,?,?)}"), SQL_NTS));
//==================================================== // Parametry
// RETURN_VALUE lnStrLen_or_IndPtr[0] = 0; DBTRY(SQLBindParameter(m_hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &lnRetVal, sizeof(long), &lnStrLen_or_IndPtr[0]));
// pvchName lnStrLen_or_IndPtr[1] = SQL_TEXTTYPE(pvchName); DBTRY(SQLBindParameter(m_hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 80, 0, (LPVOID)pvchName, 80, &lnStrLen_or_IndPtr[1]));
// pData lcbParamSize = pData->m_dwDataLength; lnStrLen_or_IndPtr[2] = SP_BLOB(lcbParamSize); DBTRY(SQLBindParameter(m_hstmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, lcbParamSize, 0, (LPVOID)pData, lcbParamSize, &lnStrLen_or_IndPtr[2]));
// pnID lnStrLen_or_IndPtr[3] = sizeof(long); DBTRY(SQLBindParameter(m_hstmt, 4, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (LPVOID)pnID, sizeof(long), &lnStrLen_or_IndPtr[3])); //==================================================== // Teraz wykonaj DBTRY(SQLExecute(m_hstmt));
if (lSQLres==SQL_NEED_DATA){ lSQLres = SaveBLOBs(); }
while (::SQLMoreResults(m_hstmt)!=SQL_NO_DATA) {};
DBTRY(SQLFreeStmt(m_hstmt, SQL_RESET_PARAMS));
if (lSQLres!=SQL_SUCCESS) AfxThrowDBException(lSQLres, m_pDatabase, m_hstmt);
return lnRetVal; };
//********************************************************************** SQLRETURN CBergenStoredProcs::SaveBLOBs(){ CLongBinary *lpData; SQLRETURN lres = ::SQLParamData(m_hstmt, (SQLPOINTER*)&lpData); //====================================================== while (lres==SQL_NEED_DATA){ int lcbSize = lpData->m_dwDataLength; LPBYTE lpbyData = (LPBYTE)GlobalLock(lpData->m_hData); //---------------------------------------------- if (SQLPutData(m_hstmt, lpbyData, lcbSize)==SQL_ERROR){ ::SQLCancel(m_hstmt); return SQL_ERROR; } //---------------------------------------------- GlobalUnlock(lpData->m_hData); lres = ::SQLParamData(m_hstmt, (SQLPOINTER*)&lpData); } //====================================================== return lres; }
//************************************************************** #define DBTRY(x)\ if (lSQLres==SQL_SUCCESS)\ lSQLres = (::x)
#define SQL_TEXTTYPE(x)\ ((x)==NULL ? SQL_NULL_DATA : SQL_NTS)
#define SP_BLOB(x)\ (x==0 ? SQL_NULL_DATA : SQL_LEN_DATA_AT_EXEC(x))
#define SQL_TEXT(x) (SQLCHAR*)(x) #define DB_TIMESTAMP_PRECISION 23
Unfortunately the return state was SQL_SUCCESS and SQLGetDiagRec didn't return any additional information.
|