2013-02-06 65 views
0

我想从我的SQL数据库中提取一个字符串,但由于某种原因,我的参数是错误的,我不知道为什么。这里是我的代码:如何使用ODBC(C++)作为字符串从MS SQL获取nvarchar?

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); 

它运行正常,但不会得到我所要求的字符串信息,而第二个参数(获得一个整数)工作正常。我已经尝试将ParameterType更改为多个不同的东西,但是我要么收到错误(例如,SQL_LONGVARCHAR已被弃用)。

在SQL中,我试图让数据如下:

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

在此先感谢任何人谁可以在此线索。我一整天都在拉我的头发。

回答

2

ODBC支持Unicode parameter types所以分别使用SQL_C_WCHARSQL_WVARCHAR代替SQL_C_CHARSQL_VARCHAR

您还有其他两个问题。

首先,您将通过ANSI string作为参数。如果您使用Unicode,则需要使用宽字符串 - wstring

第二,你没有通过有效的缓冲区SQLBindParameter。由string.c_str()返回的值是一个const char*,它是一个只读缓冲区。将帽子传递给需要可写缓冲区的函数是无效的 - 这样做会损坏您的字符串。但是,在您的情况下,您不会看到任何损坏,因为您致电path.length()将返回零,因此SQLBindParameter将永不返回任何数据。

您需要声明WCHAR数组缓冲区,并将其传递给SQLBindParameter,这将为其提供一个有效的缓冲区来写入数据。如果您需要在C++对象中,则可以将该缓冲区传输到wstring

因此,像这样:

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); 

编辑

Ffrom看着它看来,你应该能够得到ODBC该数据从Unicode转换为ANSI为您ODBC data conversion table,如果你不想在应用程序中处理Unicode字符串。

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); 
+0

非常感谢您提供的信息丰富且准确的答案。非常感谢! –

+0

我不确定你是正确的“如果你使用Unicode,你需要使用一个宽字符串”,然后编辑。即使您使用为ODBC定义的unicode构建应用程序,也应该能够将SQL_VARCHAR传递给SQLBindParameter,并且驱动程序应该返回给您一个ansi字符串。此外,传递SQL_WVARCHAR但提供一个char路径[401]仍然会在路径中放置较宽的chrs而不是ansi chrs。 – bohica

相关问题