How do I get an nvarchar from MS SQL as string using ODBC (C++)?

纵然是瞬间 提交于 2019-12-13 04:10:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!