| SQL 類型 | ODBC C 類型標識 | 備註 |
| INT / INTEGER | SQL_C_LONG | ⚠️ 無 SQL_C_INT,必須用 LONG |
| VARCHAR(n) | SQL_C_CHAR | 緩衝區大小 ≥ n+1,含結束符 |
| CHAR(n) | SQL_C_CHAR | 固定長度,不足補空格 |
三、完整插入示例:員工信息批量入庫
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
typedef struct {
long num;
char name[21];
char sex[11];
long age;
char shenfennum[21];
char xueli[11];
char mianmao[11];
char mima[21];
char quanxian[11];
char born[21];
} Worker;
Worker gong[100]; // 假設已填充數據
void workertianjiashuju(int i) {
SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt;
SQLRETURN ret;
SQLINTEGER cb = SQL_NTS; // 長度指示器
// 1. 環境、連接、語句句柄分配
SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// 2. 連接數據庫(DSN=phonesql, 用戶=sa, 密碼=123456)
ret = SQLConnect(hdbc, (SQLCHAR*)"phonesql", SQL_NTS,
(SQLCHAR*)"sa", SQL_NTS, (SQLCHAR*)"123456", SQL_NTS);
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
printf("連接失敗\\n"); goto cleanup;
}
// 3. 準備參數化 SQL
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
SQLCHAR *sql = (SQLCHAR*)"INSERT INTO worker VALUES (?,?,?,?,?,?,?,?,?,?)";
SQLPrepare(hstmt, sql, SQL_NTS);
// 4. 綁定 10 個參數(順序必須與建表一致!)
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &gong[i].num, 0, &cb);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20, 0, gong[i].name, 20, &cb);
SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 10, 0, gong[i].sex, 10, &cb);
SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &gong[i].age, 0, &cb);
SQLBindParameter(hstmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20, 0, gong[i].shenfennum, 20, &cb);
SQLBindParameter(hstmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 10, 0, gong[i].xueli, 10, &cb);
SQLBindParameter(hstmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 10, 0, gong[i].mianmao, 10, &cb);
SQLBindParameter(hstmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20, 0, gong[i].mima, 20, &cb);
SQLBindParameter(hstmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 10, 0, gong[i].quanxian, 10, &cb);
SQLBindParameter(hstmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20, 0, gong[i].born, 20, &cb);
// 5. 執行插入
ret = SQLExecute(hstmt);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
printf("第 %d 條插入成功\\n", i+1);
else
printf("插入失敗\\n");
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
cleanup:
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
四、關鍵注意事項總結
- 參數序號從 1 開始,且必須與建表列順序、SQL 中
? 位置一一對應。
- 整型參數必須取地址:
&gong[i].num,字符數組名本身即地址。
- 字符緩衝區大小:
BufferLength 應 ≥ 實際最大長度 + 1(留給 \0)。
- 錯誤處理:生產代碼中每個 ODBC 調用後應檢查返回值,失敗時調用
SQLError 獲取詳細信息。
- 事務控制:默認自動提交;批量插入建議關閉自動提交(
SQLSetConnectAttr(..., SQL_AUTOCOMMIT_OFF)),循環綁定執行後統一 SQLEndTran(SQL_COMMIT)。
五、資源清理順序
語句句柄 → 連接句柄 → 環境句柄,嚴格按相反分配順序釋放,防止資源洩漏。
掌握 SQLBindParameter 的類型映射、參數序號對應、緩衝區管理,即可構建高效、安全的 C 語言數據庫應用。參數化查詢不僅防止 SQL 注入,還能讓數據庫複用執行計劃,大幅提升批量操作性能。
- 上一篇文章: C語言隨機數生成:rand() 與 srand() 完整使用指南
- 下一篇文章: 解決 Visual Studio 2013「This function or variable may be unsafe」編譯錯誤
Copyright ©
程式碼之家 All Rights Reserved