C如何连接MSSQL数据库

1. 简介

Microsoft SQL Server,通常简称为MSSQL,是一种关系型数据库管理系统。与其他数据库一样,MSSQL可以使用多种编程语言来操作,例如C语言。

2. 连接配置

2.1 下载SQL Server驱动

在使用C语言连接MSSQL之前,需要下载相应的驱动程序。其中,Microsoft官网提供的ODBC驱动较为常见。

官网下载地址:https://www.microsoft.com/zh-CN/download/details.aspx?id=36434

下载安装后,需要在电脑的ODBC数据源管理器中添加数据源,以下是具体步骤:

打开ODBC数据源管理器

在“用户数据源”或“系统数据源”中,点击“添加”

选择“ODBC驱动程序 for SQL Server”并选择“完成”

填写MSSQL的相关信息,例如MSSQL的IP地址、数据库名称、登录名、密码等

保存配置并测试连接是否成功

2.2 连接代码实现

连接MSSQL所需的头文件和库文件如下:

#include <windows.h>

#include <sql.h>

#include <sqlext.h>

#pragma comment(lib, "odbc32.lib")

#pragma comment(lib, "odbccp32.lib")

其中,sql.hsqlext.h是提供ODBC支持的文件,Windows API中包含了这两个文件。

连接MSSQL数据库的代码如下(其中,部分易发生错误的代码以标记):

SQLHENV env;

SQLHDBC dbc;

SQLHSTMT stmt;

SQLRETURN ret;

char* connectString = "DSN=YOUR_DSN_NAME";

ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);

if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {

fprintf(stderr, "Couldn't allocate handle.\n");

goto error;

}

ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {

fprintf(stderr, "Couldn't set the environment attribute.\n");

goto error;

}

ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);

if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {

fprintf(stderr, "Couldn't allocate handle.\n");

goto error;

}

// 连接MSSQL数据库

SQLCHAR* inConnection = (SQLCHAR*)connectString;

SQLSMALLINT inConnectionLength = SQL_NTS;

ret = SQLDriverConnect(dbc, NULL, inConnection, inConnectionLength, NULL, 0, NULL, SQL_DRIVER_COMPLETE_REQUIRED);

if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {

fprintf(stderr, "Couldn't connect to database.\n");

goto error;

}

// 获取数据库版本

SQLCHAR versionBuff[1024];

SQLSMALLINT length;

SQLINTEGER needLength;

SQLExecDirect(stmt, (SQLCHAR*)"SELECT @@version", SQL_NTS);

/* 如果被选择数据大于0行,那么将结果集中的数据绑定到变量中 */

SQLBindCol(stmt, 1, SQL_C_CHAR, versionBuff, sizeof(versionBuff), &length);

ret = SQLFetch(stmt);

if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {

fprintf(stderr, "Couldn't execute SQL statement.\n");

goto error;

}

printf("MSSQL version: %s\n", versionBuff);

SQLDisconnect(dbc);

error:

SQLFreeHandle(SQL_HANDLE_ENV, env);

代码含义:

首先定义所需的句柄和返回值

使用SQLAllocHandle函数为环境、连接和语句创建句柄

使用SQLSetEnvAttr函数设置ODBC版本为ODBC 3.x

使用SQLDriverConnect函数连接数据库,其中需要传入DSN参数

使用SQLExecDirect函数执行SQL语句

使用SQLBindCol将结果集中的数据绑定到变量中

使用SQLFetch函数获取结果集的一行数据

使用SQLDisconnect函数断开连接

使用SQLFreeHandle函数释放句柄

2.3 连接池

在应用程序需要高并发执行SQL语句时,连接池可以提高应用程序的性能和响应速度。连接池是通过缓存和重用数据库连接来实现的。

在C语言中使用连接池前,需要先构建连接池。连接池的构建通常遵循以下步骤:

初始化连接池中的所有连接

创建一个“已用连接”队列和一个“未用连接”队列

连接池在开始运行后,所有的连接都在“未用连接”队列中

当需要连接数据库时,应用程序从“未用连接”队列中取出一个连接,并将其移动到“已用连接”队列中

当使用结束后,应用程序将连接从“已用连接”队列中移动到“未用连接”队列中

下面是一个简单的连接池实现:

#define MAX_CONNECTION_POOL 20

SQLHDBC g_hDbc[MAX_CONNECTION_POOL] = {0};

BOOL g_bIsUsed[MAX_CONNECTION_POOL] = {0};

/* 连接MSSQL数据库 */

void InitPool()

{

// 创建驱动环境句柄

SQLHENV hEnv;

// 创建连接句柄

for (int i = 0; i < MAX_CONNECTION_POOL; i++)

{

SQLRETURN rc;

rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);

rc = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

rc = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &g_hDbc[i]);

}

// 连接数据库

for (int i = 0; i < MAX_CONNECTION_POOL; i++)

{

char connectString[256];

snprintf(connectString, sizeof(connectString), "DSN=%s", "YOUR_DSN_NAME");

SQLCHAR* inConnection = (SQLCHAR*)connectString;

SQLSMALLINT inConnectionLength = SQL_NTS;

rc = SQLDriverConnect(g_hDbc[i], NULL, inConnection, inConnectionLength, NULL, 0, NULL, SQL_DRIVER_COMPLETE_REQUIRED);

if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {

fprintf(stderr, "couldn't connect to database : %d.", rc);

continue;

}

}

}

SQLHDBC GetConnectionFromPool()

{

int index = -1;

for (int i = 0; i < MAX_CONNECTION_POOL; i++)

{

if (g_bIsUsed[i] == false)

{

index = i;

break;

}

}

if (index == -1)

{

return NULL;

}

g_bIsUsed[index] = true;

return g_hDbc[index];

}

void PushConnectionToPool(SQLHDBC hDesc)

{

for (int i = 0; i < MAX_CONNECTION_POOL; i++)

{

if (g_hDbc[i] == hDesc)

{

g_bIsUsed[i] = false;

}

}

}

连接池实现的关键就是将所有的连接预先创建并缓存到一个数组中,并在需要连接数据库时从数组中取出一个未被占用的连接,并标记它被占用。使用结束后,再将连接标记为空闲。

3. 数据库操作

3.1 插入数据

插入一条数据的代码如下:

SQLCHAR sql[] = "USE YOUR_DATABASE_NAME INSERT INTO YOUR_TABLE_NAME(id, name) VALUES(1, 'test')";

SQLExecDirect(stmt, (SQLCHAR*)sql, SQL_NTS);

代码含义:

首先需要使用USE命令选择要使用的数据库

然后,使用INSERT INTO命令插入数据,其中YOUR_TABLE_NAME需要替换成要插入数据的表名

使用SQLExecDirect函数执行SQL语句

3.2 查询数据

查询一条数据的代码如下:

SQLCHAR sql[256];

sprintf((char*)sql, "USE YOUR_DATABASE_NAME SELECT * FROM YOUR_TABLE_NAME WHERE id = %d", 1);

SQLExecDirect(stmt, (SQLCHAR*)sql, SQL_NTS);

SQLSMALLINT id;

SQLCHAR name[64];

SQLINTEGER nameLen;

/* 如果被选择数据大于0行,那么将结果集中的数据绑定到变量中 */

SQLBindCol(stmt, 1, SQL_C_SSHORT, &id, sizeof(id), NULL);

SQLBindCol(stmt, 2, SQL_C_CHAR, name, sizeof(name), &nameLen);

while(SQLFetch(stmt) != SQL_NO_DATA) {

printf("id=%d, name=%s\n", id, name);

}

代码含义:

首先需要使用USE命令选择要使用的数据库

然后,使用SELECT命令查询数据,其中YOUR_TABLE_NAME需要替换成要查询数据的表名

使用SQLExecDirect函数执行SQL语句

使用SQLBindCol将结果集中的数据绑定到变量中

使用SQLFetch函数获取结果集的一行数据,并输出

3.3 更新数据

更新一条数据的代码如下:

SQLCHAR sql[256];

sprintf((char*)sql, "USE YOUR_DATABASE_NAME UPDATE YOUR_TABLE_NAME SET name = 'new_name' WHERE id = %d", 1);

SQLExecDirect(stmt, (SQLCHAR*)sql, SQL_NTS);

代码含义:

首先需要使用USE命令选择要使用的数据库

然后,使用UPDATE命令更新数据,其中YOUR_TABLE_NAME需要替换成要更新数据的表名

使用SQLExecDirect函数执行SQL语句

3.4 删除数据

删除一条数据的代码如下:

SQLCHAR sql[256];

sprintf((char*)sql, "USE YOUR_DATABASE_NAME DELETE FROM YOUR_TABLE_NAME WHERE id = %d", 1);

SQLExecDirect(stmt, (SQLCHAR*)sql, SQL_NTS);

代码含义:

首先需要使用USE命令选择要使用的数据库

然后,使用DELETE FROM命令删除数据,其中YOUR_TABLE_NAME需要替换成要删除数据的表名

使用SQLExecDirect函数执行SQL语句

4. 结论

本文介绍了如何使用C语言连接MSSQL数据库,包括连接配置、数据库操作等,还介绍了连接池的实现方法,希望对大家有所帮助。

数据库标签