C++ CRUD programming for DB

1、ODBC

        开放数据库互连,微软主导的关系型数据库接口标准,允许同一代码访问不同DBMS中的数据。小案例:C++连接Access数据库----增删改查_c++ access数据库-CSDN博客

·ODBC(Open Database Connectivity,开放数据库连接)

        ODBC是Microsoft公司为应用程序访问关系型数据库时提供的一组标准接口规范。ODBC对不同的关系型数据库提供了统一的API,使用该API来访问任何提供了ODBC驱动程序的数据库。

··ODBC的构成

··ODBC的体系结构

        其中,应用程序是我们自己写的,通过API接口,调用驱动程序管理器,各类关系型数据库需提供自己的ODBC驱动程序。

··数据库ODBC驱动管理与安装

        在 运行 中输入 odbcad32 可启动 odbc数据源管理器,如果没有需要的数据库驱动,需自行下载安装。安装ODBC方法-CSDN博客

··ODBC的优点

··ODBC自研

ODBC微软官方参考文档:Microsoft ODBC Driver for SQL Server - ODBC Driver for SQL Server | Microsoft Learn

·ODBC编程的步骤

··配置数据源

安装ODBC方法-CSDN博客

··代码分步详解

相关头文件

//ODBC操作数据库需要包含的头文件
#include <windows.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <sql.h>

代码主体
1、初始化环境句柄
//############################### Step  1 ####################
// 1、分配ODBC环境句柄
SQLHANDLE hEnv = NULL;   // 环境句柄
if (SQL_ERROR == SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv)) {std::cout << "分配环境句柄失败!\n";return -1;
}
// 2、设定ODBC版本
if (SQL_ERROR == SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER)) {std::cout << "ODBC版本设定失败!\n";return -1;
}
2、初始化连接句柄
//############################### Step  2 ####################
// 1、分配连接句柄(应用程序可以连接到数据源或驱动程序之前,它必须分配一个连接句柄
SQLHANDLE hDbc = NULL;   // 数据库连接句柄
// 2、初始化数据库连接句柄
SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
3、连接数据库
	//############################### Step  3 ####################// 1、根据DSN连接连接数据库//法1// 	SQLCHAR* connStr = (SQLCHAR*)"DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:\\MyAccess\\test.accdb"; //数据库路径// 	SQLRETURN ret = SQLDriverConnect(hDbc, NULL, connStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);//if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {//	std::cout << "数据库连接成功!" << std::endl;//}//法2/*SQLRETURN ret = SQLConnect(hDbc, (SQLTCHAR*)_T("数据源名称"), SQL_NTS,(SQLTCHAR*)_T("用户名"), SQL_NTS,(SQLTCHAR*)_T("密码"), SQL_NTS);*/SQLRETURN ret = SQLConnect(hDbc, (SQLTCHAR*)_T("AccessODBC"), SQL_NTS,NULL, SQL_NTS,NULL, SQL_NTS);if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {std::cout << "数据库连接成功!" << std::endl;}else if (ret == SQL_ERROR) {SQLTCHAR state[128] = { 0 };SQLTCHAR msg[128] = { 0 };//获取错误信息(参数 连接句柄,环境句柄,语句句柄...)ret = SQLError(hEnv, hDbc, NULL, state, NULL, msg, sizeof(msg), NULL);_tprintf(_T("%s %s\n"), state, msg);}
4、初始化语句句柄
//############################### Step  4 ####################
// 插入数据// 分配语句句柄
SQLHSTMT hStmt = NULL;
ret = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);
···执行INSERT语句(几种写法) 
//准备SQL语句
SQLTCHAR sql[] = _T("INSERT INTO 通讯录 VALUES(10,'凌敏','女','21','131422','China')"); //无“?”版本
ret = SQLPrepare(hStmt, sql, SQL_NTS);//执行SQL语句
ret = SQLExecute(hStmt);

注意:以上SQL语句的写法,INSERT INTO 通讯录 VALUES(10,'凌敏','女','21','131422','China'),需要写出每一个属性的值,INSERT INTO 通讯录 VALUES(10,'凌敏','女','21','131422')×。

下面价绍一种复杂版的SQL语句写法

SQLTCHAR sql[] = _T("INSERT INTO 通讯录 VALUES(?,?,?,?,?,?)"); //复杂版
// 复杂版下的参数传递
//6个参数
SQLINTEGER id = 124;
SQLTCHAR name[32] = _T("lvtu");
SQLTCHAR sex[32] = _T("男");
SQLTCHAR age[32] = _T("25");
SQLTCHAR num[32] = _T("3123124");
SQLTCHAR country[32] = _T("CHINA");//绑定SQL语句的参数
ret = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, 0, 0, (SQLPOINTER)&id, 0, NULL);
ret = SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, sizeof(name), 0, (SQLPOINTER)name, 0, NULL);
ret = SQLBindParameter(hStmt, 3, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, sizeof(sex), 0, (SQLPOINTER)sex, 0, NULL);
ret = SQLBindParameter(hStmt, 4, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, sizeof(age), 0, (SQLPOINTER)age, 0, NULL);
ret = SQLBindParameter(hStmt, 5, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR,  sizeof(num), 0,(SQLPOINTER)num, 0, NULL);
ret = SQLBindParameter(hStmt, 6, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR,  sizeof(country), 0,(SQLPOINTER)country, 0, NULL);
ret = SQLPrepare(hStmt, sql, SQL_NTS);

其中,SQLBindParameter参数介绍

以上用到了两种执行语句,分别是:SQLExecute和SQLExecDirect,区别在于:前者用来执行由SQLPrepare创建的的sql语句,后者直接执行,语句在运行时被编译并执行。

SQLExecute是执行已准备的SQL语句,SQLExecDirect是提交SQL语句一次执行的最快方法。

···执行SELECT语句

步骤为:分配语句句柄-》准备SQL语句-》执行SQL语句-》绑定结果集的列(很重要!)-》遍历查询结果-》查看被查询的行数

//############################### Step  5 ####################
// 查询数据// 分配语句句柄
SQLHSTMT hStmt = NULL;
ret = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);//准备SQL语句
SQLTCHAR sql[] = _T("SELECT * FROM 通讯录");//执行SQL语句
ret = SQLExecDirect(hStmt, sql, SQL_NTS);  //SL_NTS可以自动计算sql的长度
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {std::wcout << _T("数据库查询成功!") << std::endl;//查询之后,所有数据放到了一块缓冲区,我们需要把他分离出来INT ID = 0;TCHAR name[32] = { 0 };TCHAR sex[10] = { 0 };TCHAR age[10] = { 0 };TCHAR phone[32] = { 0 };TCHAR country[32] = { 0 };SQLLEN len = SQL_NTS;SQLBindCol(hStmt, 1, SQL_C_SHORT, &ID, sizeof(ID), 0);SQLBindCol(hStmt, 2, SQL_C_WCHAR, name, sizeof(name), &len);SQLBindCol(hStmt, 3, SQL_C_WCHAR, sex, sizeof(sex), &len);SQLBindCol(hStmt, 4, SQL_C_WCHAR, age, sizeof(age), &len);SQLBindCol(hStmt, 5, SQL_C_WCHAR, phone, sizeof(phone), &len);SQLBindCol(hStmt, 6, SQL_C_WCHAR, country, sizeof(country), &len);//逐行遍历,获取数据ret = SQLFetch(hStmt);SHORT count = 0;while (ret != SQL_NO_DATA) {++count;std::wcout << ID << "\t" << name << "\t" << sex << "\t"<< age << "\t" << phone << "\t" << country << "\t" << std::endl;//每次清除一下上行旧数据,保证下次获取的数据干净ID = 0;ZeroMemory(name, sizeof(name));ZeroMemory(sex, sizeof(sex));ZeroMemory(age, sizeof(age));ZeroMemory(phone, sizeof(phone));ZeroMemory(country, sizeof(country));//获取下一行数据,填充到 ID ,Name......ret = SQLFetch(hStmt);}看一下一共查了几行
//SQLLEN n = 0;
//ret = SQLRowCount(hStmt, &n);  //查询被影响的行数 
//if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
//	_tprintf(_T("查询%d行数据成功!\n"), n);
//}
_tprintf(_T("查询%d行数据成功!\n"), count);

一般而言,查询被影响的行数可以用SQLRowCount函数,但是

对于查询操作,SQLRowCount可能不会返回预期的结果,特别是在某些数据库管理系统中,它可能返回-1,表示无法确定影响的行数。这是因为在查询操作中,数据库可能不会跟踪或无法确定实际检索的行数,特别是当使用了游标或者在数据量大的情况下。

为了避免这种情况,可以不使用SQLRowCount来获取查询结果的行数。相反,可以使用一个计数器变量在遍历结果集时递增,这样在遍历结束后,计数器中的值就是查询结果的实际行数。

···执行DELETE语句
//############################### Step  6 ####################
//删除操作
//分配语句句柄
SQLHSTMT  hStmt = NULL;
ret = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);//SQL删除语句 
//SQLTCHAR sql[] = _T("DELETE FROM  通讯录 WHERE  iID = 2");//简单版本
SQLTCHAR sql[] = _T("DELETE FROM  通讯录 WHERE  iID = ?");//复杂版本//准备SQL语句
ret = SQLPrepare(hStmt, sql, SQL_NTS);//SQL_NTS自动计算sql语句的长度//复杂版本绑定SQL语句的参数 
int id = 2;
ret = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, 0, NULL);//执行SQL语句
ret = SQLExecute(hStmt);
if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO) || (ret == SQL_NO_DATA))  //SQL_NO_DATA表示受影响行数为0
{SQLLEN n = 0;ret = SQLRowCount(hStmt, &n);//查询被影响的行数(适用于SELECT ,INSERT,UPDATE,DELETE操作)if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO){_tprintf(_T("删除%d行数据成功!\n"), n);}}
else if (ret == SQL_ERROR)
{SQLTCHAR   state[128] = { 0 };SQLTCHAR   msg[128] = { 0 };//获取错误信息,注意填写语句句柄ret = SQLError(hEnv, hDbc, hStmt, state, NULL, msg, sizeof(msg), NULL);std::wcout << state << "   " << msg << std::endl;
}
 ```执行UPDATE语句
//############################### Step  7 ####################
//修改数据
//分配语句句柄SQLHSTMT  hStmt = NULL;ret = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);//SQL修改语句 //SQLTCHAR sql[] = _T("UPDATE    通讯录 SET  iName='小雪'   WHERE  iSex = '女’");//简单版本SQLTCHAR sql[] = _T("UPDATE    通讯录 SET  iName=?  WHERE  iSex = ? ");//复杂版本//准备SQL语句ret = SQLPrepare(hStmt, sql, SQL_NTS);//SQL_NTS自动计算sql语句的长度//复杂版本绑定SQL语句的参数  SQLLEN len = SQL_NTS;SQLTCHAR  newName[50] = _T("小雪");ret = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, 50, 0, (SQLPOINTER)newName, 0, &len);int id = 1000;ret = SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, 0, NULL);//执行SQL语句ret = SQLExecute(hStmt);if ((ret == SQL_SUCCESS) || (ret == SQL_SUCCESS_WITH_INFO)){SQLLEN n = 0;ret = SQLRowCount(hStmt, &n);//查询被影响的行数(适用于SELECT ,INSERT,UPDATE,DELETE操作)if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO){_tprintf(_T("修改%d行数据成功!\n"), n);}}else if (ret == SQL_ERROR){SQLTCHAR   state[128] = { 0 };SQLTCHAR   msg[128] = { 0 };//获取错误信息,注意填写语句句柄ret = SQLError(hEnv, hDbc, hStmt, state, NULL, msg, sizeof(msg), NULL);std::wcout << state << "   " << msg << std::endl;}
···释放资源

注意顺序:语句执行完先释放语句句柄,接着关闭数据库连接,然后释放连接句柄,最后释放环境句柄。

	// 释放句柄//释放语句句柄if (hStmt) {ret = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);}// 关闭数据库连接ret = SQLDisconnect(hDbc);if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {std::wcout << _T("数据库关闭成功!") << std::endl;}//释放连接句柄if (hDbc) {ret = SQLFreeHandle(SQL_HANDLE_DBC, hDbc);}//释放环境句柄if (hEnv) {ret = SQLFreeHandle(SQL_HANDLE_ENV, hEnv);}
代码中错误显示函数介绍 

ODBC连接MySQL数据库(CRUD)

1、创建一个MYSQL数据库

2、下载安装MySQL数据库ODBC驱动和配置MySQL ODBC数据源

下载下载安装MySQL数据库ODBC驱动和配置MySQL ODBC数据源_mysql odbc 8.0 unicode driver 下载-CSDN博客

配置: (本地就填127.0.0.1)

3、代码

/*
SQLRETURN ret = SQLConnect(hDbc, (SQLTCHAR*)_T("数据源名称"), SQL_NTS,
    (SQLTCHAR*)_T("用户名"), SQL_NTS,
    (SQLTCHAR*)_T("密码"), SQL_NTS);
*/
SQLRETURN ret = SQLConnect(hDbc, (SQLTCHAR*)_T("MYSQLODBC"), SQL_NTS,
    (SQLTCHAR*)_T("root"), SQL_NTS,
    (SQLTCHAR*)_T("2410947747"), SQL_NTS);

修改这段。

2、OLE DB

对象连接嵌入数据库,是基于COM规范的低级别、高性能API,仅在Windows上可用。

3、ADO

活动数据对象,ADO向我们提供了一个高层的对OLE DB的封装接口。ADO是对当前微软所支持的数据库进行操作的最简单直接和最有效的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2980442.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

PCB的通孔、盲孔、埋孔

通孔&#xff1a;是从顶层到底层 盲孔&#xff1a;看不到头&#xff0c;跟井一样&#xff0c;起点永远是第一层 埋孔&#xff1a;是正反都看不到的 总结&#xff1a; 这些孔都是用来切换层的

超详细的Maven安装与使用还有内容讲解

文章目录 作用简介模型仓库 安装配置IDEA配置Maven坐标概念主要组成 IDEA创建Maven项目基本使用常用命令生命周期使用坐标导入jar包 注意事项清理maven仓库更新索引依赖 作用 Maven是专门用于管理和构建Java项目的工具&#xff0c;它的主要功能有&#xff1a; 提供了一套标准化…

力扣HOT100 - 101. 对称二叉树

解题思路&#xff1a; class Solution {public boolean isSymmetric(TreeNode root) {if(root null) return true;return recur(root.left, root.right);}boolean recur(TreeNode L, TreeNode R) {if (L null && R null) return true;if (L null || R null || L.…

基于深度学习网络的十二生肖图像分类matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................... for i 1:16subplot(4,4,…

第七章 信息系统维护与管理

文章目录 一&#xff0c;概述二&#xff0c;信息系统的使用&#xff08;一&#xff09;用户培训&#xff08;二&#xff09;系统转换&#xff08;三&#xff09;系统运行 三&#xff0c;信息系统的维护&#xff08;一&#xff09;信息系统维护过程1&#xff0c;维护组织2&#…

Meta Llama 3本地部署

感谢阅读 环境安装收尾 环境安装 项目文件 下载完后在根目录进入命令终端&#xff08;windows下cmd、linux下终端、conda的话activate&#xff09; 运行 pip install -e .不要控制台&#xff0c;因为还要下载模型。这里挂着是节省时间 模型申请链接 复制如图所示的链接 然后…

mongodb 安装问题

1. mongodb启动时显示 Illegal instruction (core dumped) mongodb 5.0之后(包括5.0) 开始使用需要使用 AVX 指令集 2.启动时报错 ERROR: child process failed, exited with 1 通过指令 bin/mongod --repair 查看报错信息 根据报错信息进行修改 3. 配置服务器添加节点时…

【北京迅为】《iTOP-3588开发板系统编程手册》-第19章 V4L2摄像头应用编程

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

企商在线亮相2024中国生成式AI大会,展出多元异构算力服务

4月18—19日&#xff0c;由知名媒体机构智东西与智猩猩共同主办的2024中国生成式AI大会在北京举行&#xff0c;55位重量级产学研投界代表同台分享。企商在线作为算力行业代表企业&#xff0c;参展生成式AI展区&#xff0c;现场展出企商在线AI算力平台及异构算力服务。 大会以“…

三分钟快速理解Flink 作业提交流程(包工头的工程之路)

核心组件 我们先来简单了解一下 flink 作业提交涉及到的组件 同时&#xff0c;如果不了解 Yarn 的同学欢迎跳转到这篇文章&#xff0c;了解一下健鑫集团的工程承包流程(doge): 三分钟快速理解Yarn的工作流程 JobManager JobManager 是整个flink作业的管理者 包含 Dispatch…

“PowerInfer:消费级GPU上的高效大型语言模型推理引擎“

PowerInfer是由上海交通大学IPADS实验室开发的一个高效大型语言模型&#xff08;LLM&#xff09;推理引擎&#xff0c;专为个人电脑&#xff08;PC&#xff09;上的消费者级GPU设计。它通过利用LLM推理中的高局部性&#xff0c;实现了快速且资源消耗低的模型推理&#xff0c;这…

深入探究图像增强(C语言实现)

我们将从基础出发使用C语言进行图像处理与分析&#xff0c;重点讨论图像增强和平滑技术。图像增强技术旨在通过增加对比度、亮度和整体清晰度来改善图像的视觉质量。另一方面&#xff0c;图像平滑方法则用于减少噪声并减少图像中的突变&#xff0c;使图像更加均匀和视觉上吸引人…

Github Copilot正版的激活成功,终于可以chat了

Github Copilot 代码补全等功能&#xff0c;提高写代码的效率 https://web.52shizhan.cn/activity/copilot 登录授权后&#xff0c;已经可以使用&#xff0c;完美。如图

OpenFE:开启数据特征工程新时代

OpenFE&#xff1a;开启数据特征工程新时代 数据特征工程是机器学习和数据分析领域中至关重要的一环&#xff0c;它涉及对原始数据进行处理和转换&#xff0c;以提取出有用的特征&#xff0c;为模型构建和预测提供更好的输入。在这个领域中&#xff0c;Python库OpenFE为数据科学…

查找两个字符串的最长公共子串

暴力解法 #include <iostream> #include <vector> #include <cstring> using namespace std; string a, b, minn ""; // a和b是我们输入的 // minn存储的是我们最小的那个字符串string cut(int l, int r) {string tmp "";for (int i …

大小端解释以及如何使用程序判断IDE的存储模式

今天让我们来了解一下大小端的概念吧 什么是大小端&#xff1f; 大端&#xff08;存储&#xff09;模式&#xff1a;指的是数据的低位保存在内存的高地址处&#xff0c;而数据的高位则保存在内存的低地址处。 小端&#xff08;存储&#xff09;模式&#xff1a;指的是数据的低位…

Discuz! X系列版本安装包

源码下载地址&#xff1a;Discuz! X系列版本安装包 很多新老站长跟我说要找Discuz! X以前的版本安装包&#xff0c;我们做Discuz! X开发已经十几年了&#xff0c;这些都是官方原版安装包&#xff0c;方便大家使用&#xff08;在官网已经找不到这些版本的安装包了&#xff09; …

新网站上线需要注意什么?

质量保证&#xff1a;确保网站的所有功能和页面都经过了充分的测试&#xff0c;并且在各种不同的浏览器和设备上都能够正常运行。检查所有链接、表单和交互式元素&#xff0c;确保它们都能够按照预期工作。优化性能&#xff1a;确保网站加载速度快&#xff0c;响应迅速。优化图…

详细UI色彩搭配方案分享

UI 配色是设计一个成功的用户界面的关键之一。UI 配色需要考虑品牌标志、用户感受、应用程序的使用场景&#xff0c;这样可以帮助你创建一个有吸引力、易于使用的应用程序。本文将分享 UI 配色的相关知识&#xff0c;帮助设计师快速构建 UI 配色方案&#xff0c;以满足企业的需…

环回光模块

&#x1f44f;&#x1f4cd;环回光模块&#xff08;Lookback&#xff09;&#xff0c;也称为光模块自环测试回路器&#xff0c;用于测试系统或网络中的信号回传。通过回传信号&#xff08;主要是成对连接发射端到接收端的一侧&#xff09;&#xff0c;可以检测网络链路中各种潜…