当前位置: 首页 > news >正文

unixODBC编程(十)分片插入长数据

遇到有LONG数据类型的表,要插入一条数据量很大的行,一次插入的缓冲区会不够大,这时需要一部分一部分的插入LONG数据,这就用到了在执行语句时动态提供数据的机制。在ODBC中要动态提供数据需要几个步骤。

1. 在绑定输入参数时,要在SQLBindParameter()函数中指定数据长度时,使用SQL_LEN_DATA_AT_EXEC()宏得到数据长度,告诉应用程序数据在执行语句时才提供,使用的数据类型要用SQL_LONGVARCHAR或SQL_LONGBINARY。同时数据指针要提供一个数值,标记这个字段,为了区分多个动态插入的字段,这个数值在后面调用SQLParamData()函数时会返回,这样应用程序就知道现在是哪个字段需要提供数据。

2. 执行SQLExecute()或SQLExecDirect()函数,因为语句中有动态字段,所以函数会返回SQL_NEED_DATA的返回值。

3. 调用SQLParamData()函数,返回标识字段的数值,这时就知道是为哪个字段插入数据。函数返回SQL_NEED_DATA,这时需要提供数据。

4. 循环调用SQLPutData()函数,为字段提供动态数据,直到插入的数据完毕。

5. 再次调用SQLParamData()函数,看看是否还有下一个动态插入的字段需要操作,函数返回SQL_NEED_DATA,说明需要为新字段提供数据,重复步骤4的操作。如果返回SQL_SUCCESS,说明没有要提供数据的字段了,把上一个动态插入数据的系列操作结束。

举一个例子,在test_long1表中插入LONG数据,字段叫summary,插入10000个字符。SQLBindParameter()函数的StrLen_or_IndPtr参数设置为SQL_LEN_DATA_AT_EXEC(10000),ParameterType设置为SQL_LONGVARCHAR,ParameterValuePtr设置为参数的编号,比如编号为3,那么函数设置如下。

len_ind3 = SQL_LEN_DATA_AT_EXEC(10000);
SQLBindParameter(stmth, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 10000, 0, (void *)3, 0, &len_ind3);
下面我们看一个实际的例子,在test_long1表中插入一条数据,绑定三个参数,后面两个参数都使用动态提供数据,主要看看SQLParamData()函数和SQLPutData()函数的用法,以及如何动态提供数据。代码如下。

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sql.h"
#include "sqlext.h"
#include "sqltypes.h"SQLHANDLE       envh;           /* env handle */
SQLHANDLE       dbch;           /* connect handle */
SQLHANDLE       stmth;          /* statement handle */int main(int argc, char *argv[])
{int         conn = 0;SQLRETURN   rc;SQLLEN      len_ind1;SQLLEN      len_ind2;SQLLEN      len_ind3;SQLLEN      total_amt;SQLLEN      once_amt;SQLINTEGER  id;SQLPOINTER  param_id;char        dsn_str[32];char        usrname[32];char        passwd[32];char        sqltxt[512];char        data[4096];if (argc < 3) {fprintf(stderr, "usage: %s dsn username password\n", argv[0]);return (-1);}strncpy(dsn_str, argv[1], 32);dsn_str[31] = '\0';strncpy(usrname, argv[2], 32);usrname[31] = '\0';strncpy(passwd, argv[3], 32);passwd[31] = '\0';rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &envh);if (rc != SQL_SUCCESS) {fprintf(stderr, "Allocate environment handle error.\n");return (-1);}rc = SQLSetEnvAttr(envh, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);if (rc != SQL_SUCCESS) {fprintf(stderr, "Set ODBC version error.\n");goto free_exit;}rc = SQLAllocHandle(SQL_HANDLE_DBC, envh, &dbch);if (rc != SQL_SUCCESS) {fprintf(stderr, "Allocate DB connection handle error.\n");goto free_exit;}rc = SQLSetConnectAttr(dbch, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)10, 0);if (rc != SQL_SUCCESS) {fprintf(stderr, "Set connection timeout value error.\n");goto free_exit;}rc = SQLConnect(dbch, (SQLCHAR *)dsn_str, SQL_NTS, (SQLCHAR *)usrname, SQL_NTS,(SQLCHAR *)passwd, SQL_NTS);if (rc != SQL_SUCCESS) {fprintf(stderr, "Connect to DB error.\n");goto free_exit;}conn = 1;fprintf(stdout, "connect DB ok ......\n");rc = SQLAllocHandle(SQL_HANDLE_STMT, dbch, &stmth);if (rc != SQL_SUCCESS) {fprintf(stderr, "Allocate statment handle error.\n");goto free_exit;}/* 插入一条数据,输入三个参数,note和summary动态提供数据 */sprintf(sqltxt, "insert into test_long1 (id, name, addr, note, summary) values (?, 'AAAAAAAA', 'BBBBBBBBBB', ?, ?)");rc = SQLPrepare(stmth, (SQLCHAR *)sqltxt, SQL_NTS);if (rc != SQL_SUCCESS) {fprintf(stderr, "Prepare statment error.\n");goto free_exit;}/* ID字段的插入值为10 */id = 10;/* ID正常插入,在绑定时提供数值* NOTE在执行时动态提供数据,长度为40,数据为40个'C'字符,一次提供完毕* SUMMARY在执行是动态提供数据,长度为10000,数据为10000个'D'字符,分多次提供* NOTE和SUMMARY字段使用SQL_LEN_DATA_AT_EXEC()宏计算长度*/len_ind1 = 0;len_ind2 = SQL_LEN_DATA_AT_EXEC(40);len_ind3 = SQL_LEN_DATA_AT_EXEC(10000);/* 绑定变量id */rc = SQLBindParameter(stmth, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,0, 0, &id, 0, &len_ind1);if (rc != SQL_SUCCESS) {fprintf(stderr, "Bind column 1 error.\n");goto free_exit;}/* 参数类型为SQL_LONGVARCHAR,数据指针指向参数编号2 */rc = SQLBindParameter(stmth, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,2000, 0, (void *)2, 0, &len_ind2);if (rc != SQL_SUCCESS) {fprintf(stderr, "Bind column 2 error.\n");goto free_exit;}/* 参数类型为SQL_LONGVARCHAR,数据指针指向参数编号3 */rc = SQLBindParameter(stmth, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,10000, 0, (void *)3, 0, &len_ind3);if (rc != SQL_SUCCESS) {fprintf(stderr, "Bind column 3 error.\n");goto free_exit;}/* 执行插入语句,这时函数返回SQL_NEED_DATA */rc = SQLExecute(stmth);if ((rc != SQL_SUCCESS) && (rc != SQL_NEED_DATA)) {fprintf(stderr, "Execute statment error.\n");goto free_exit;}/* 循环检查动态提供数据的字段 */while (1) {/* 调用SQLParamData()函数,parma_id返回绑定时指定的参数编号 */rc = SQLParamData(stmth, &param_id);if ((rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))/* 返回SQL_SUCCESS说明所有动态提供数据的字段都操作完成了,退出循环 */break;if (rc != SQL_NEED_DATA) {/* 这里如果返回值不为SQL_NEED_DATA说明函数调用出错了 */fprintf(stderr, "Call SQLParamData() error.\n");goto free_exit;}if (param_id == (SQLPOINTER)2) {/* param_id等于2,说明要为第二个参数提供数据,提供40个'C'字符 */memset(data, 'C', 40);data[40] = '\0';len_ind2 = 40;/* 调用SQLPutData()函数,为参数2提供数据 */rc = SQLPutData(stmth, (SQLPOINTER)data, len_ind2);if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) {fprintf(stderr, "Call SQLPutData() error.\n");goto free_exit;}} else if (param_id == (SQLPOINTER)3) {/* param_id等于3,说明要为第三个参数提供数据,提供10000个'D'字符* 每次提供4000字符,分三次提供完毕*/once_amt = 4000;total_amt = 10000;memset(data, 'D', 4000);data[4000] = '\0';while (total_amt > once_amt) {/* 每次提供4000字符 */rc = SQLPutData(stmth, (SQLPOINTER)data, once_amt);if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) {fprintf(stderr, "Call SQLPutData() error.\n");goto free_exit;}total_amt -= once_amt;}if (total_amt > 0) {/* 提供最后的2000字符 */rc = SQLPutData(stmth, (SQLPOINTER)data, total_amt);if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO)) {fprintf(stderr, "Call SQLPutData() error.\n");goto free_exit;}}} else {fprintf(stderr, "Invalid parameter number.\n");goto free_exit;}}/* 提交改变的数据 */rc = SQLEndTran(SQL_HANDLE_DBC, dbch, SQL_COMMIT);if (rc != SQL_SUCCESS) {fprintf(stderr, "End Transaction error.\n");goto free_exit;}fprintf(stdout, "Insert data successed ......\n");SQLFreeHandle(SQL_HANDLE_STMT, stmth);SQLDisconnect(dbch);SQLFreeHandle(SQL_HANDLE_DBC, dbch);SQLFreeHandle(SQL_HANDLE_ENV, envh);return (0);free_exit:if (stmth != NULL) {SQLFreeHandle(SQL_HANDLE_STMT, stmth);}if (conn) {SQLDisconnect(dbch);}if (dbch != NULL) {SQLFreeHandle(SQL_HANDLE_DBC, dbch);}if (envh != NULL) {SQLFreeHandle(SQL_HANDLE_ENV, envh);}return (-1);
}

访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。

相关文章:

unixODBC编程(十)分片插入长数据

遇到有LONG数据类型的表&#xff0c;要插入一条数据量很大的行&#xff0c;一次插入的缓冲区会不够大&#xff0c;这时需要一部分一部分的插入LONG数据&#xff0c;这就用到了在执行语句时动态提供数据的机制。在ODBC中要动态提供数据需要几个步骤。 1. 在绑定输入参数时&…...

【Java】—— 集合框架:Collection子接口:Set不同实现类的对比及使用(HashSet、LinkedHashSet、TreeSet)

目录 5. Collection子接口2&#xff1a;Set 5.1 Set接口概述 5.2 Set主要实现类&#xff1a;HashSet 5.2.1 HashSet概述 5.2.2 HashSet中添加元素的过程&#xff1a; 5.2.3 重写 hashCode() 方法的基本原则 5.2.4 重写equals()方法的基本原则 5.2.5 练习 5.3 Set实现类…...

android Activity生命周期

android 中一个 activity 在其生命周期中会经历多种状态。 您可以使用一系列回调来处理状态之间的转换。下面我们来介绍这些回调。 onCreate&#xff08;创建阶段&#xff09; 初始化组件&#xff1a;在这个阶段&#xff0c;Activity的主要工作是进行初始化操作。这包括为Ac…...

C#的面向对象

1&#xff09;对象 算法数据结构 2&#xff09;对象的行为已方法的形式定义的&#xff0c;属性以成员变量的形式定义的 面向对象程序设计的特点 1&#xff09;封装性 2&#xff09;继承性 3&#xff09;多态性 知识点&#xff1a; 封装性面向对象的核心思想&#xff0c;将…...

【区别】三种命令取消已暂存的文件,处理暂存区和文件的跟踪状态

取消已暂存的文件 git restore --staged <文件>、git reset HEAD <文件> 和 git rm --cached <文件> 都可以用于取消已暂存的文件&#xff0c;但它们的作用和使用场景略有不同。下面是它们的区别&#xff1a; 1. git restore --staged <文件> 该命令…...

如何在Spring Boot中有条件地运行CommandLineRunner Bean

PS 使用 Spring Boot 3.1.2 进行测试 1.使用ConditionalOnProperty ConditionalOnProperty仅当特定属性存在或具有特定值时&#xff0c;注释才会创建 Bean 。 在此示例中&#xff0c;仅当或文件中的CommandLineRunner属性db.init.enabled设置为 true时&#xff0c;才会执行。…...

边缘自适应粒子滤波(Edge-Adaptive Particle Filter)的MATLAB函数示例,以及相应的讲解

目录 讲解 初始化 预测步骤 观测模拟 权重更新 重采样 状态估计 总结 下面是一个简单的边缘自适应粒子滤波&#xff08;&#xff09;的函数示例&#xff0c;以及相应的讲解。 程序源代码&#xff1a; function X_est edgeAdaptiveParticleFilter(numParticles, numS…...

一块1T硬盘怎么有sdb1和sdb2

在一块 1TB 硬盘上看到两个分区 sdb1 和 sdb2 是非常常见的现象。硬盘可以被划分为多个分区&#xff0c;每个分区都可以用作不同的目的&#xff0c;如存储不同类型的数据、安装不同的操作系统或为系统不同的功能提供支持。 1. 分区的概念 硬盘可以被划分为多个分区&#xff0…...

Python知识点:如何使用Flink与Python进行实时数据处理

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 如何使用Flink与Python进行实时数据处理 Apache Flink是一个流处理框架&#xf…...

Swagger配置且添加小锁(asp.net)(笔记)

此博客是基于 asp.net core web api(.net core3.1)框架进行操作的。 一、安装Swagger包 在 NuGet程序包管理中安装下面的两个包&#xff1a; swagger包&#xff1a;Swashbuckle.AspNetCore swagger包过滤器&#xff1a;Swashbuckle.AspNetCore.Filters 二、swagger注册 在…...

lambda表达式底层实现:反编译LambdaMetafactory + 转储dump + 运行过程 + 反汇编 + 动态指令invokedynamic

一、结论先行 lambda 底层实现机制 1.lambda 表达式的本质&#xff1a;函数式接口的匿名子类的匿名对象 2.lambda表达式是语法糖 语法糖&#xff1a;编码时是lambda简洁的表达式&#xff0c;在字节码期&#xff0c;语法糖会被转换为实际复杂的实现方式&#xff0c;含义不变&am…...

Unity初识+面板介绍

Unity版本使用 小版本号高&#xff0c;出现bug可能性更小&#xff1b;一台电脑可以安装多个版本的Unity&#xff0c;但是需要安装在不同路径&#xff1b;安装Unity时不能有中文路径&#xff1b;Unity项目路径也不要有中文。 Scene面板 相当于拍电影的片场&#xff0c;Unity程…...

【CSS in Depth 2 精译_041】6.4 CSS 中的堆叠上下文与 z-index(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09;第二章 相对单位&#xff08;已完结&#xff09;第三章 文档流与盒模型&#xff08;已完结&#xff09;第四章 Flexbox 布局&#xff08;已…...

uniapp微信小程序巧用跳转封装鉴权路由

1.这是封装的跳转方法&#xff1a; import store from "../stores/store";function Router(type, url, params) {const NoLoginPage [。。。。。];var queryString Object.keys(params).map((key) > ${key}${params[key]}).join("&");if (!NoLog…...

国外电商系统开发-运维系统开发

因项目运营环境在国外&#xff0c;所以必须将服务器选择国外&#xff0c;加上第一次运营国外项目。在两大趋势下&#xff0c;企业的运营方向必须通过大数据来分析及修正运营方向&#xff0c;加上后期服务器数量日益增多&#xff0c;如何有效的管理众多的服务器及验证运营方向&a…...

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…...

【艾思科蓝】机器学习框架终极指南:PyTorch vs TensorFlow vs Keras vs Scikit-learn

第十届建筑、土木与水利工程国际学术会议(ICACHE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看&#xff1a;学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 1. PyTorch PyTorch的特点 PyTorch的用例 PyTorch的安装 PyTorch代码示例 2. TensorFlow …...

招联金融秋招内推2025

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…...

遮罩解决图片悬浮操作看不到的情况

未悬浮效果 悬浮效果 如果仅仅是添加绝对定位&#xff0c;那么遇到白色图片&#xff0c;就会看不到白色字体。通过遮罩&#xff08;绝对定位透明度&#xff09;就可以解决这个问题。 <script setup> </script><template><div class"box"><…...

IoT网关的主要功能有哪些?天拓四方

在数字化浪潮席卷全球的今天&#xff0c;物联网&#xff08;IoT&#xff09;技术凭借其独特的优势&#xff0c;逐渐在各个领域展现出强大的生命力。而IoT网关&#xff0c;作为连接物理世界与数字世界的桥梁&#xff0c;其在物联网体系中的作用愈发凸显。 一、数据聚合与预处理…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...