问题
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.
回答1:
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);
来源:https://stackoverflow.com/questions/14735665/how-do-i-get-an-nvarchar-from-ms-sql-as-string-using-odbc-c