/*
這個文件里封裝了很多操作資料庫的函數
參考資料:https://msdn.microsoft.com/en-us/library/ms714562%28v=vs.85%29.aspx
*/
#include <stdio.h>
#include <Windows.h>
#include <sqlext.h>
#include "db.h"
SQLHENV hEnv;
SQLHDBC hConn;
SQLRETURN rc;
// 連接到資料庫
int db_connect()
{
char szCode[6] = "";
char szTemp[256] = "";
SQLAllocHandle(SQL_HANDLE_ENV, NULL, &hEnv);
SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, (SQLINTEGER)NULL);
SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hConn);
rc = SQLDriverConnectA(hConn, NULL, (SQLCHAR *)DB_DSN, SQL_NTS, NULL, (SQLSMALLINT)NULL, NULL, (SQLSMALLINT)NULL);
if (!SQL_SUCCEEDED(rc))
{
// 連接失敗的錯誤提示
puts("無法連接資料庫!");
rc = SQLGetDiagRecA(SQL_HANDLE_DBC, hConn, 1, (SQLCHAR *)szCode, NULL, (SQLCHAR *)szTemp, sizeof(szTemp) - 1, NULL);
if (SUCCEEDED(rc))
{
printf("錯誤代碼: %s\n", szCode);
printf("錯誤信息: %s\n", szTemp);
}
else
puts("未知錯誤");
return 0; // 連接失敗時,函數返回0
}
return 1; // 連接成功時,函數返回1
}
// 關閉資料庫連接並釋放資源
void db_disconnect()
{
SQLDisconnect(hConn);
SQLFreeHandle(SQL_HANDLE_DBC, hConn);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
}
// 執行SQL查詢
void *db_prepare(char *sql)
{
SQLHSTMT hStmt;
SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
SQLPrepareA(hStmt, (SQLCHAR *)sql, strlen(sql));
return hStmt;
}
void *db_query(char *sql)
{
void *stmt = db_prepare(sql);
SQLExecute(stmt);
return stmt;
}
void db_exec(char *sql)
{
void *stmt = db_query(sql);
db_free(stmt);
}
int db_exec_stmt(void *stmt)
{
int f = SQL_SUCCEEDED(SQLExecute(stmt));
db_free(stmt);
return f;
}
// 釋放資源
void db_free(void *stmt)
{
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
// 獲取一行
int db_fetch(void *stmt)
{
return SQL_SUCCEEDED(SQLFetch(stmt));
}
// 以整數類型保存第col列的內容
void db_bind_int(void *stmt, int col, int *p)
{
SQLBindCol(stmt, col, SQL_C_LONG, p, sizeof(int), NULL);
}
// 以字元串類型保存第col列的內容
void db_bind_str(void *stmt, int col, char *buf, int len)
{
SQLBindCol(stmt, col, SQL_C_CHAR, buf, len, NULL);
}
// 以小數類型保存第col列的內容
void db_bind_float(void *stmt, int col, float *p)
{
SQLBindCol(stmt, col, SQL_C_FLOAT, p, sizeof(float), NULL);
}
int db_has_records(char *sql)
{
void *stmt = db_query(sql);
int r = db_fetch(stmt);
db_free(stmt);
return r;
}
void db_set_int(void *stmt, int i, int *p)
{
static SQLLEN size = sizeof(int); // 該變數的地址必須固定, 所以要加static
SQLBindParameter(stmt, i, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, (SQLUINTEGER)NULL, (SQLSMALLINT)NULL, p, (SQLINTEGER)NULL, &size); // 整型變數的地址也必須固定
}
void db_set_str(void *stmt, int i, char *s)
{
static SQLLEN len = SQL_NTS;
SQLBindParameter(stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, strlen(s), (SQLSMALLINT)NULL, s, (SQLINTEGER)NULL, &len);
}