C++ 数据库使用 SQL ODBC 从 table 获取行数组
C++ Database get array of rows from a table using SQL ODBC
参考这个linkC++\SQL ODBC: Get row from table
我不理解这些文档,并尝试了很多变体来使某些东西起作用,但它只是输出完全乱码。基本上,我如何从我的 Microsoft Access 数据库中获取数据到我的 C++ 程序中。我最终想要将整个 table 存储为数组或向量,也就是说,假设我的 table 中有 5 个字段,我想存储(在 5 个不同的数组或向量中)所有内容到相应的字段。但是现在,我怎么能只拥有一个名为“Example Table”的 table 之类的东西,并且其中有一个名为“Names”的字段,类型是字符串或“短文本”作为 Access调用它。然后如何将其加载到字符串或 char* 数组中以用于我的 GUI 或程序的其他部分?这是我当前的代码:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <sqlext.h>
#include <iostream>
WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\Users\Name\Desktop\databaseExample\databaseExample\Data.accdb";
int _tmain(int argc, _TCHAR* argv[])
{
HENV hEnv;
HDBC hDbc;
/* ODBC API return status */
RETCODE rc;
int iConnStrLength2Ptr;
WCHAR szConnStrOut[256];
const WCHAR* query = L"select Names from Example_Table";
HSTMT hStmt;
/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);
/* Connect to the database */
rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
SQL_NTS, (WCHAR*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
wprintf(L"Successfully connected to database. Data source name: \n %s\n",
szConnStrOut);
/* Prepare SQL query */
wprintf(L"SQL query:\n %s\n", query);
rc = SQLAllocStmt(hDbc, &hStmt);
rc = SQLPrepare(hStmt, (SQLWCHAR*)query, SQL_NTS);
/* Excecute the query */
rc = SQLExecute(hStmt);
if (SQL_SUCCEEDED(rc))
{
wprintf(L"SQL Success\n");
}
else {
wprintf(L"SQL Failed\n");
}
}
else
{
wprintf(L"Couldn't connect to %s.\n", szDSN);
}
/* Disconnect and free up allocated handles */
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
getchar();
printf("hi\n");
return 0;
}
您需要使用 SQLGetData,传递 SQL_C_WCHAR 类型,例如,如果您的列是文本。下面是如何获取单个文本列的值并将它们放入向量的示例:
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>
#include <sqlext.h>
WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\Test\users.accdb";
void DisplayError(SQLSMALLINT t, SQLHSTMT h) {
SQLWCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT i, MsgLen;
SQLRETURN rc;
SQLLEN numRecs = 0;
SQLGetDiagField(t, h, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
// Get the status records.
i = 1;
while (i <= numRecs && (rc = SQLGetDiagRec(t, h, i, SqlState, &NativeError,
Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
wprintf(L"Error %d: %s\n", NativeError, Msg);
i++;
}
}
std::vector<std::wstring> ExecuteSql(const WCHAR* sql) {
std::vector<std::wstring> results = {};
HENV hEnv = NULL;
HDBC hDbc = NULL;
HSTMT hStmt = NULL;
int iConnStrLength2Ptr;
WCHAR szConnStrOut[256];
SQLINTEGER rowCount = 0;
SQLSMALLINT fieldCount = 0;
SQLWCHAR buf[128];
SQLINTEGER ret;
/* ODBC API return status */
RETCODE rc;
/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);
/* Connect to the database */
rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
SQL_NTS, (WCHAR*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
/* Prepare SQL query */
rc = SQLAllocStmt(hDbc, &hStmt);
rc = SQLPrepare(hStmt, (SQLWCHAR*)sql, SQL_NTS);
/* Excecute the query */
rc = SQLExecute(hStmt);
if (SQL_SUCCEEDED(rc))
{
SQLNumResultCols(hStmt, &fieldCount);
if (fieldCount > 0)
{
/* Loop through the rows in the result set */
rc = SQLFetch(hStmt);
while (SQL_SUCCEEDED(rc))
{
//get data
rc = SQLGetData(hStmt, 1, SQL_C_WCHAR, buf, sizeof(buf), &ret);
if (SQL_SUCCEEDED(rc) == FALSE) {
wprintf(L"SQLGetData failed\n");
continue;
}
//convert data to string
std::wstring str;
if (ret <= 0) {
str = std::wstring(L"(null");
}
else {
str = std::wstring(buf);
}
results.push_back(str);
rc = SQLFetch(hStmt);
rowCount++;
};
rc = SQLFreeStmt(hStmt, SQL_DROP);
}
else
{
wprintf(L"Error: Number of fields in the result set is 0.\n");
}
}
else {
wprintf(L"SQL Failed\n");
DisplayError(SQL_HANDLE_STMT, hStmt);
}
}
else
{
wprintf(L"Couldn't connect to %s\n", szDSN);
DisplayError(SQL_HANDLE_DBC, hDbc);
}
/* Disconnect and free up allocated handles */
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
return results;
}
int main()
{
auto results = ExecuteSql(L"SELECT name FROM Users");
for (auto x : results) {
std::wcout << x << std::endl;
}
getchar();
return 0;
}
参考这个linkC++\SQL ODBC: Get row from table 我不理解这些文档,并尝试了很多变体来使某些东西起作用,但它只是输出完全乱码。基本上,我如何从我的 Microsoft Access 数据库中获取数据到我的 C++ 程序中。我最终想要将整个 table 存储为数组或向量,也就是说,假设我的 table 中有 5 个字段,我想存储(在 5 个不同的数组或向量中)所有内容到相应的字段。但是现在,我怎么能只拥有一个名为“Example Table”的 table 之类的东西,并且其中有一个名为“Names”的字段,类型是字符串或“短文本”作为 Access调用它。然后如何将其加载到字符串或 char* 数组中以用于我的 GUI 或程序的其他部分?这是我当前的代码:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <sqlext.h>
#include <iostream>
WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\Users\Name\Desktop\databaseExample\databaseExample\Data.accdb";
int _tmain(int argc, _TCHAR* argv[])
{
HENV hEnv;
HDBC hDbc;
/* ODBC API return status */
RETCODE rc;
int iConnStrLength2Ptr;
WCHAR szConnStrOut[256];
const WCHAR* query = L"select Names from Example_Table";
HSTMT hStmt;
/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);
/* Connect to the database */
rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
SQL_NTS, (WCHAR*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
wprintf(L"Successfully connected to database. Data source name: \n %s\n",
szConnStrOut);
/* Prepare SQL query */
wprintf(L"SQL query:\n %s\n", query);
rc = SQLAllocStmt(hDbc, &hStmt);
rc = SQLPrepare(hStmt, (SQLWCHAR*)query, SQL_NTS);
/* Excecute the query */
rc = SQLExecute(hStmt);
if (SQL_SUCCEEDED(rc))
{
wprintf(L"SQL Success\n");
}
else {
wprintf(L"SQL Failed\n");
}
}
else
{
wprintf(L"Couldn't connect to %s.\n", szDSN);
}
/* Disconnect and free up allocated handles */
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
getchar();
printf("hi\n");
return 0;
}
您需要使用 SQLGetData,传递 SQL_C_WCHAR 类型,例如,如果您的列是文本。下面是如何获取单个文本列的值并将它们放入向量的示例:
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>
#include <sqlext.h>
WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\Test\users.accdb";
void DisplayError(SQLSMALLINT t, SQLHSTMT h) {
SQLWCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT i, MsgLen;
SQLRETURN rc;
SQLLEN numRecs = 0;
SQLGetDiagField(t, h, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
// Get the status records.
i = 1;
while (i <= numRecs && (rc = SQLGetDiagRec(t, h, i, SqlState, &NativeError,
Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
wprintf(L"Error %d: %s\n", NativeError, Msg);
i++;
}
}
std::vector<std::wstring> ExecuteSql(const WCHAR* sql) {
std::vector<std::wstring> results = {};
HENV hEnv = NULL;
HDBC hDbc = NULL;
HSTMT hStmt = NULL;
int iConnStrLength2Ptr;
WCHAR szConnStrOut[256];
SQLINTEGER rowCount = 0;
SQLSMALLINT fieldCount = 0;
SQLWCHAR buf[128];
SQLINTEGER ret;
/* ODBC API return status */
RETCODE rc;
/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);
/* Connect to the database */
rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
SQL_NTS, (WCHAR*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
/* Prepare SQL query */
rc = SQLAllocStmt(hDbc, &hStmt);
rc = SQLPrepare(hStmt, (SQLWCHAR*)sql, SQL_NTS);
/* Excecute the query */
rc = SQLExecute(hStmt);
if (SQL_SUCCEEDED(rc))
{
SQLNumResultCols(hStmt, &fieldCount);
if (fieldCount > 0)
{
/* Loop through the rows in the result set */
rc = SQLFetch(hStmt);
while (SQL_SUCCEEDED(rc))
{
//get data
rc = SQLGetData(hStmt, 1, SQL_C_WCHAR, buf, sizeof(buf), &ret);
if (SQL_SUCCEEDED(rc) == FALSE) {
wprintf(L"SQLGetData failed\n");
continue;
}
//convert data to string
std::wstring str;
if (ret <= 0) {
str = std::wstring(L"(null");
}
else {
str = std::wstring(buf);
}
results.push_back(str);
rc = SQLFetch(hStmt);
rowCount++;
};
rc = SQLFreeStmt(hStmt, SQL_DROP);
}
else
{
wprintf(L"Error: Number of fields in the result set is 0.\n");
}
}
else {
wprintf(L"SQL Failed\n");
DisplayError(SQL_HANDLE_STMT, hStmt);
}
}
else
{
wprintf(L"Couldn't connect to %s\n", szDSN);
DisplayError(SQL_HANDLE_DBC, hDbc);
}
/* Disconnect and free up allocated handles */
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
return results;
}
int main()
{
auto results = ExecuteSql(L"SELECT name FROM Users");
for (auto x : results) {
std::wcout << x << std::endl;
}
getchar();
return 0;
}