| 方案 | 適用資料庫 | 優點 | 缺點 | 推薦場景 |
|---|---|---|---|---|
| ODBC | 通用 (SQL Server, MySQL, Oracle, PG...) | 標準化、跨平台、驅動豐富 | 效能稍低、API 繁瑣 | 跨資料庫專案、Linux/Unix |
| OLE DB | Windows 專用 (SQL Server, Oracle, Access...) | COM 模型、功能豐富、Windows 效能佳 | 僅限 Windows、微軟已停止更新 | 舊式 Windows 桌面應用 |
| 原生庫 | 特定資料庫 | 效能最高、功能全、原生體驗 | 綁定廠商、需分發客戶端 | 高效能、深度整合專案 |
#include
#include
#include
#include
void checkError(SQLRETURN ret, SQLHANDLE handle, SQLSMALLINT type, const char* msg) {
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
SQLCHAR sqlState[6], message[1024];
SQLINTEGER nativeError;
SQLSMALLINT len;
SQLGetDiagRec(type, handle, 1, sqlState, &nativeError, message, sizeof(message), &len);
std::cerr << msg << ": " << message << std::endl;
}
}
int main() {
SQLHENV hEnv; SQLHDBC hDbc; SQLHSTMT hStmt;
SQLRETURN ret;
// 1. 分配環境句柄
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
checkError(ret, hEnv, SQL_HANDLE_ENV, "AllocEnv");
SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// 2. 分配連接句柄
ret = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
checkError(ret, hDbc, SQL_HANDLE_DBC, "AllocDbc");
// 3. 連接 (使用 DSN)
ret = SQLConnect(hDbc, (SQLCHAR*)"MyDSN", SQL_NTS, (SQLCHAR*)"user", SQL_NTS, (SQLCHAR*)"pwd", SQL_NTS);
checkError(ret, hDbc, SQL_HANDLE_DBC, "Connect");
// 4. 分配語句句柄並執行查詢
SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);
ret = SQLExecDirect(hStmt, (SQLCHAR*)"SELECT GETDATE()", SQL_NTS);
checkError(ret, hStmt, SQL_HANDLE_STMT, "ExecDirect");
// 5. 綁定列並提取
SQL_TIMESTAMP_STRUCT ts;
SQLLEN indicator;
SQLBindCol(hStmt, 1, SQL_C_TYPE_TIMESTAMP, &ts, 0, &indicator);
while (SQLFetch(hStmt) == SQL_SUCCESS) {
std::cout << ts.year << "-" << ts.month << "-" << ts.day << " "
<< ts.hour << ":" << ts.minute << ":" << ts.second << std::endl;
}
// 6. 清理
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
return 0;
}
Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=Test;UID=sa;PWD=123;#include
using namespace mysqlx;
int main() {
try {
Session sess("localhost", 33060, "user", "pwd");
Schema db = sess.getSchema("test");
Table table = db.getTable("users");
RowResult res = table.select("id", "name").where("id > :id").bind("id", 10).execute();
for (Row row : res.fetchAll()) {
std::cout << row[0] << ": " << row[1] << std::endl;
}
} catch (const Error &e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
class DbConnection {
SQLHDBC hDbc_;
public:
DbConnection(const std::string& connStr) { /* SQLDriverConnect */ }
~DbConnection() { if (hDbc_) SQLDisconnect(hDbc_); }
// 禁用拷貝,支援移動
DbConnection(const DbConnection&) = delete;
DbConnection& operator=(const DbConnection&) = delete;
DbConnection(DbConnection&&) noexcept = default;
// 執行查詢、參數綁定等封裝方法...
};
選型原則:跨平台/多資料庫選 ODBC,Windows 專用高效能選原生庫,避開 OLE DB。