Question

I'm trying to extract a string from my SQL database, but for some reason my parameters are wrong and I'm not sure why. Here is my code:

SQLHENV environHandle;
SQLHDBC connectHandle;
SQLHSTMT statement;
SQLCHAR* connectString = "MY_CONNECTION_STRING";
string path;
int jobID;  
SQLINTEGER pathstrlen = SQL_NTS;

SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &environHandle);
SQLSetEnvAttr(environHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
SQLAllocHandle(SQL_HANDLE_DBC, environHandle, &connectHandle);
SQLDriverConnect(connectHandle, NULL, connectString, SQL_NTS, NULL, 1024, NULL, SQL_DRIVER_NOPROMPT);
SQLAllocHandle(SQL_HANDLE_STMT, connectHandle, &statement);

//THIS IS THE BINDPARAMETER WITH THE ISSUE...
SQLBindParameter(statement, 1, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 400, 0, (SQLPOINTER)path.c_str(), path.length(), &pathstrlen);

SQLBindParameter(statement, 2, SQL_PARAM_OUTPUT, SQL_INTEGER, SQL_INTEGER, 10, 0, &jobID, 0, &pathstrlen);

SQLExecDirect(statement, (SQLCHAR*)"{CALL SP(?,?)}", SQL_NTS);

It runs fine, but won't get the string information I requested, while the second parameter (to get an integer) works fine. I've tried changing the ParameterType to multiple different things but I either get errors thrown at me (SQL_LONGVARCHAR for example, is deprecated).

In SQL, the data I'm trying to get is as follows:

@Path nvarchar(4000) OUT
set @Path = 'test'

Thanks in advance to anyone who can shed light on this. I've been pulling my hair out all day.

Was it helpful?

Solution

ODBC supports Unicode parameter types so use SQL_C_WCHAR and SQL_WVARCHAR instead of SQL_C_CHAR and SQL_VARCHAR respectively.

You have two other issues as well.

First you are passing an ANSI string as a parameter. If you are using Unicode you need to use a wide string - wstring instead.

Second you are not passing a valid buffer to SQLBindParameter. The value returned by string.c_str() is a const char* that is a read only buffer. It is not valid to pass hat to a function that requires a writable buffer - doing this will corrupt your string. However you won't see any corruption in your case because you the call to path.length() WILL return zero so SQLBindParameter will never return any data.

You will need to declare WCHAR array buffer and pass that to SQLBindParameter which will give it a valid buffer to write data into. You can then transfer that buffer to a wstring if you need it in a C++ object.

So something like this:

WCHAR path[401];  // 401 - width of you column + 1 for the null terminator
SQLBindParameter(statement, 1, SQL_PARAM_OUTPUT, SQL_C_WCHAR, SQL_WVARCHAR, 400, 0,     (SQLPOINTER)path, sizeof(path), &pathstrlen);

Edit

Ffrom looking at the ODBC data conversion table it appears that you should be able to get ODBC to convert that data from Unicode to ANSI for you if you to not want to deal with Unicode strings in your application.

char path[401];  // 401 - width of you column + 1 for the null terminator
SQLBindParameter(statement, 1, SQL_PARAM_OUTPUT, SQL_C_WCHAR, SQL_WVARCHAR, 400, 0,     (SQLPOINTER)path, sizeof(path), &pathstrlen);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top