1. 前言
C语言操作SQL Server数据库是比较常见的需求,本文将介绍一些实用的技巧,帮助大家更好地操作SQL Server数据库。
2. 连接SQL Server数据库
2.1 链接准备工作
在C语言中,连接SQL Server数据库需要使用Windows API提供的ODBC接口程序。使用ODBC API时,需要做以下准备工作:
安装SQL Server 的ODBC驱动程序,可以在 Microsoft官方网站下载。
让ODBC Driver API工作,需要在程序中引入ODBC Driver Manager库(odbc32.lib,在Windows SDK中提供)。
2.2 进行连接
连接SQL Server需要以下步骤:
调用SQLAllocHandle函数申请一个数据连接句柄。
调用SQLConnect函数连接数据库。
调用SQLAllocHandle函数申请执行语句的语句句柄。
代码实现如下:
SQLHANDLE henv;
SQLHANDLE hdbc;
SQLHANDLE hstmt;
SQLCHAR *dsn = (SQLCHAR*)"Driver={SQL Server};Server=IP;Database=DB;Uid=sa;Pwd=pwd";
SQLRETURN ret;
//申请数据连接句柄
ret = SQLAllocHandle ( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv );
//设置ODBC版本
ret = SQLSetEnvAttr ( henv, SQL_ATTR_ODBC_VERSION, ( void *) SQL_OV_ODBC3, 0 );
//申请连接句柄
ret = SQLAllocHandle ( SQL_HANDLE_DBC, henv, &hdbc );
ret = SQLDriverConnect ( hdbc, NULL, dsn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE );
//申请执行语句的语句句柄
ret = SQLAllocHandle ( SQL_HANDLE_STMT, hdbc, &hstmt );
3. 执行SQL语句
3.1 普通SQL语句的执行
执行INSERT、UPDATE、DELETE、SELECT等SQL语句的方法一样。只需要使用SQLExecDirect执行sql语句即可。
代码实现如下:
char sql[] = "INSERT INTO table_name (column1,column2,column3) VALUES (value1,value2,value3)";
//执行sql语句
SQLRETURN ret = SQLExecDirect ( hstmt, (UCHAR *) sql, SQL_NTS );
if ( ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO ) {
//操作成功
}
3.2 带参数的SQL语句执行
可以使用参数化sql来避免SQL注入漏洞的风险和简化SQL语句的书写。
代码实现如下:
SQLCHAR *sql2 = (SQLCHAR*)"INSERT INTO table_name VALUES (?,?)";
//申请参数句柄
SQLHANDLE hParams = SQL_NULL_HANDLE;
SQLRETURN ret2 = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hParams);
//绑定参数数据类型
SQLINTEGER nType1 = SQL_C_CHAR;
SQLCHAR szValue1[202] = "value1";
SQLINTEGER cbValue1 = SQL_NTS;
SQLRETURN ret3 = SQLBindParameter(hParams, 1, SQL_PARAM_INPUT, nType1, SQL_CHAR, 10, 0, szValue1, 0, &cbValue1);
SQLINTEGER nType2 = SQL_C_CHAR;
SQLCHAR szValue2[202] = "value2";
SQLINTEGER cbValue2 = SQL_NTS;
SQLRETURN ret4 = SQLBindParameter(hParams, 2, SQL_PARAM_INPUT, nType2, SQL_CHAR, 10, 0, szValue2, 0, &cbValue2);
//绑定语句句柄和参数句柄
SQLRETURN ret5 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)1, SQL_IS_UINTEGER);
SQLRETURN ret6 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_BIND_TYPE, (SQLPOINTER)(SQL_LEN_DATA_AT_EXEC(0)), SQL_IS_UINTEGER);
SQLRETURN ret7 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_BIND_OFFSET_PTR, 0, 0);
SQLRETURN ret8 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, 0, 0);
SQLRETURN ret9 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMSET_SQL_TYPE, SQL_PARAM_INPUT, SQL_IS_INTEGER);
SQLRETURN ret10 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, paramsStatus, SQL_IS_POINTER);
SQLRETURN ret11 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_OPERATION_PTR, paramsOperations, SQL_IS_POINTER);
SQLRETURN ret12 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_BIND_TYPE_PTR, paramValueTypes, SQL_IS_POINTER);
SQLRETURN ret13 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_BIND_OFFSET_PTR, (SQLPOINTER)paramValueOffsets, SQL_IS_POINTER);
SQLRETURN ret14 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMSET_SIZE, ¶msSize, SQL_IS_UINTEGER);
SQLRETURN ret15 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, paramsStatus, SQL_IS_POINTER);
SQLRETURN ret16 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAM_STATUS_PTR, paramsStatus, SQL_IS_POINTER);
SQLRETURN ret17 = SQLSetStmtAttr(hstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, ¶mCount, SQL_IS_POINTER);
//执行insert语句
SQLRETURN ret18 = SQLExecute(hstmt);
//释放资源
SQLFreeStmt(hstmt, SQL_CLOSE);
SQLFreeStmt(hParams, SQL_CLOSE);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
4. 查询SQL语句的结果集
4.1 遍历结果集
结果集可以循环遍历,使用SQLFetch()函数可以获取下一条记录。
代码实现如下:
SQLCHAR szData[100] = {0};
while (SQLFetch(hstmt) == SQL_SUCCESS) {
SQLGetData(hstmt, index1, SQL_C_CHAR, szData, sizeof(szData), NULL);
printf("column1 value:%s\n", szData);
SQLGetData(hstmt, index2, SQL_C_CHAR, szData, sizeof(szData), NULL);
printf("column2 value:%s\n", szData);
}
//释放资源
SQLFreeStmt(hstmt, SQL_CLOSE);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
4.2 获取特定记录
结果集也可以通过SQLGetData函数获取特定记录。
代码实现如下:
char sql[] = "SELECT column1,column2 FROM table_name WHERE column3 = 'value3'";
SQLRETURN ret = SQLExecDirect ( hstmt, (UCHAR *) sql, SQL_NTS );
SQLCHAR szData[100] = {0};
while (SQLFetch(hstmt) == SQL_SUCCESS) {
SQLGetData(hstmt, index1, SQL_C_CHAR, szData, sizeof(szData), NULL);
printf("column1 value:%s\n", szData);
SQLGetData(hstmt, index2, SQL_C_CHAR, szData, sizeof(szData), NULL);
printf("column2 value:%s\n", szData);
}
//释放资源
SQLFreeStmt(hstmt, SQL_CLOSE);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
5. 关闭连接
完成数据操作后,需要调用以下函数关闭连接。
代码实现如下:
SQLFreeStmt(hstmt, SQL_CLOSE);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
6. 总结
C语言操作SQL Server数据库是一个比较常见的需求,但需要注意数据库连接、SQL语句的执行以及结果集的遍历。