通过ODBC实现对SQL Server数据库进行增删改查操作

      ODBC(Open Database Connectivity,开放式数据库连接)提供了一种标准的应用程序编程接口(API),来访问各种数据库管理系统(DBMS)。这些API利用SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。ODBC的设计目标是实现数据库访问的独立性和开放性,即与具体的编程语言、数据库系统和操作系统无关。大多数数据源都有ODBC驱动程序。ODBC是低级别高性能接口,专为关系数据存储而设计。

      ODBC驱动程序附带sqlcmd和bcp等工具。使用sqlcmd实用工具可以运行Transact-SQL语句、系统过程和SQL脚本。bcp实用工具可以在Microsoft SQL Server实例和用户指定格式的数据文件间大批量复制数据。使用bcp实用工具可以将大量新行导入SQL Server表,或将表数据导出到数据文件。

      Microsoft ODBC Driver for SQL Server是独立的ODBC驱动程序,是单个动态链接库(DLL),它包含对使用本机代码API连接到SQL Server的应用程序的运行时支持。

      ODBC接口的使用涉及三大块:SQL语句、ODBC函数调用,以及C编程。

      1.安装ODBC驱动程序

      (1).从 https://learn.microsoft.com 下载"Microsoft ODBC Driver 18 for SQL Server(x64)",下载后的文件名为msodbcsql.msi;

      (2).双击msodbcsql.msi进行安装:注:默认仅安装客户端组件,安装Driver SDK需选定。

      注:

      Microsoft ODBC Driver 18 for SQL Server可与Microsoft ODBC Driver 17 for SQL Server并行安装。

      对于安装了Driver 17.1.0.1或更低版本的用户,建议先手动将其卸载,然后再安装较新版本的驱动程序。

      msodbcsql.h存放在C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\180\SDK\Include目录下。

      msodbcsql18.lib存放在C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\180\SDK\Lib\x64目录下。

      动态库msodbcsql18.dll存放在C:\Windows\System32目录下。

      2.Windows10上配置ODBC数据源:数据源是数据的源以及访问该数据所需的连接信息。

      (1).依次打开:控制面板 --> 管理工具:双击打开"ODBC 数据源(64位)",如下图所示:

      (2).点击"添加",弹出的"创建新数据源"对话框中,选择SQL Server,点击完成,如下图所示:

      注:

      用户DSN(Data Source Name,数据源名称):仅对当前登录Windows的用户可见和可用。对个人开发或测试环境来说可能方便,因为它允许每个用户拥有自己独立的数据源配置。

      系统DSN:对所有登录到Windows系统的用户都可见和可用。这意味着,一旦创建了系统DSN,任何登录到该系统的用户都可以访问和使用它。这对于需要多个用户共享同一数据源配置的环境(如生产环境)非常有用。

      (3).名称:TestODBC;描述:测试ODBC;服务器:DESKTOP-P1TAS09;点击下一步,如下图所示:

      (4).选择"使用用户输入登录ID和密码的SQL Server验证";登录ID:sa;密码:spring;点击下一页,如下图所示:

      (5).勾选"更改默认的数据库为":Info;此数据库在 https://blog.csdn.net/fengbingchun/article/details/141021323 中有创建过程描述,点击下一页,如下图所示:

      (6).勾选"更改SQL Server系统消息的语言为":Simplified Chinese;点击完成,如下图所示:

      (7).点击"测试数据源",检验设置的ODBC信息是否有误,如下图所示:弹出对话框,提示"测试成功!",说明顺利连接,点击确定

      (8).可以看到多了一条用户DSN,如下图所示:

      3.通过ODBC API操作SQL Server数据库进行增删改查操作:

      测试代码test_sqlserver_odbc.cpp如下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>

namespace {
// display error/warning information
void handle_diagnostic_record(SQLHANDLE handle, SQLSMALLINT type, RETCODE code)
{
	if (code == SQL_INVALID_HANDLE) {
		std::cerr << "Error: Invalid handle" << std::endl;
		return;
	}

	SQLSMALLINT number{ 0 };
	constexpr SQLSMALLINT buffer_length{ 1024 };
	SQLCHAR state[SQL_SQLSTATE_SIZE + 1] = { 0 }, message[buffer_length] = { 0 };
	SQLINTEGER  error{ 0 };
	while (SQLGetDiagRec(type, handle, ++number, state, &error, message, buffer_length, nullptr) == SQL_SUCCESS) {
		// hide data truncated ...
		if (std::strncmp((char*)state, "01004", SQL_SQLSTATE_SIZE))
			std::cerr << "Error: " << state << "," << message << ":" << error << std::endl;
	}
}

// call ODBC functions and report an error on failure
void check_error(SQLHANDLE handle, SQLSMALLINT type, RETCODE code)
{
	if (code != SQL_SUCCESS)
		handle_diagnostic_record(handle, type, code);

	if (code == SQL_ERROR) {
		std::cerr << "Error: code: " << code << std::endl;
		std::exit(1);
	}
}

} // namespace

int test_sqlserver_odbc()
{
	// allocate an environment
	SQLHENV henv{ nullptr };
	auto ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
	if ( ret == SQL_ERROR) {
		std::cerr << "Error: Unable to allocate an environment handle" << std::endl;
		return -1;
	}

	// register this as an application that expects 3.x behavior, you must register something if you use AllocHandle
	check_error(henv, SQL_HANDLE_ENV, SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3, 0));

	// allocate a connection
	SQLHDBC hdbc{ nullptr };
	check_error(henv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc));

	// connect to the driver.use the connection string if supplied on the input,otherwise let the driver manager prompt for input
	//check_error(hdbc, SQL_HANDLE_DBC, SQLDriverConnect(hdbc, GetDesktopWindow(), (SQLCHAR*)"", SQL_NTS, nullptr, 0, nullptr, SQL_DRIVER_COMPLETE));
	check_error(hdbc, SQL_HANDLE_DBC, SQLConnect(hdbc, (SQLCHAR*)"TestODBC", SQL_NTS, (SQLCHAR*)"sa", SQL_NTS, (SQLCHAR*)"spring", SQL_NTS));
	
	SQLHSTMT hstmt{ nullptr };
	check_error(hdbc, SQL_HANDLE_DBC, SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt));

	// insert operation
	SQLCHAR sql1[] = "INSERT INTO student VALUES(1111, 'Sam', 'man', 16, '2000-12-15 08:00')";
	check_error(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, sql1, SQL_NTS));
	check_error(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt));

	SQLCHAR sql2[] = "INSERT INTO student VALUES(1112, '小李', '女', 22, '2010-12-15 08:00')";
	check_error(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, sql2, SQL_NTS));
	check_error(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt));

	// delete operation
	SQLCHAR sql5[] = "DELETE FROM student WHERE id = 1111";
	check_error(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, sql5, SQL_NTS));
	check_error(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt));

	// query operation
	SQLCHAR sql3[] = "SELECT * FROM student WHERE age > 20;";
	check_error(hstmt, SQL_HANDLE_STMT, SQLExecDirect(hstmt, sql3, SQL_NTS));

	int id{ 0 };
	char name[32] = { 0 };
	char sex[16] = { 0 };
	int age{ 0 };
	char brith[32] = { 0 };

	SQLLEN len = SQL_NTS;
	check_error(hstmt, SQL_HANDLE_STMT, SQLBindCol(hstmt, 1, SQL_INTEGER, &id, sizeof(id), 0));
	check_error(hstmt, SQL_HANDLE_STMT, SQLBindCol(hstmt, 2, SQL_CHAR, &name, sizeof(name), &len));
	check_error(hstmt, SQL_HANDLE_STMT, SQLBindCol(hstmt, 3, SQL_CHAR, &sex, sizeof(sex), &len));
	check_error(hstmt, SQL_HANDLE_STMT, SQLBindCol(hstmt, 4, SQL_INTEGER, &age, sizeof(age), 0));
	check_error(hstmt, SQL_HANDLE_STMT, SQLBindCol(hstmt, 5, SQL_CHAR, &brith, sizeof(brith), &len));

	ret = SQLFetch(hstmt);
	while (ret != SQL_NO_DATA) {
		std::cout << id << "\t" << name << "\t" << sex << "\t" << age << "\t" << brith << std::endl;

		id = 0;
		std::memset(name, 0, 32);
		std::memset(sex, 0, 16);
		age = 0;
		std::memset(brith, 0, 32);

		ret = SQLFetch(hstmt);
	}

	// delete operation
	if (hstmt)
		check_error(hdbc, SQL_HANDLE_DBC, SQLFreeHandle(SQL_HANDLE_STMT, hstmt));
	check_error(hdbc, SQL_HANDLE_DBC, SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt));

	SQLCHAR sql4[] = "DELETE FROM student WHERE id = 1112";
	check_error(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, sql4, SQL_NTS));
	check_error(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt));

	// update operation
	SQLCHAR sql6[] = "UPDATE student SET name = '小田' WHERE id = 1003";
	check_error(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, sql6, SQL_NTS));
	check_error(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt));

	// free ODBC handles
	if (hstmt)
		check_error(hdbc, SQL_HANDLE_DBC, SQLFreeHandle(SQL_HANDLE_STMT, hstmt));

	if (hdbc) {
		check_error(hdbc, SQL_HANDLE_DBC, SQLDisconnect(hdbc));
		check_error(hdbc, SQL_HANDLE_DBC, SQLFreeHandle(SQL_HANDLE_DBC, hdbc));
	}

	if (henv)
		check_error(hdbc, SQL_HANDLE_ENV, SQLFreeHandle(SQL_HANDLE_ENV, henv));

	return 0;
}

      执行插入后的结果如下图所示:id为1111和1112为新增加的数据

      执行查询后的输出结果如下图所示:查询age>20的数据

      GitHubhttps://github.com/fengbingchun/Messy_Test

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值