unixODBC编程(八)使用滚动游标

Qt无法获取mysql数据,但插入和删除数据的代码以及iodbc配置都是正确的,如何解决? 🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀! 阅读详情

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

Cursor是光标的意思,指的是在计算机屏幕上闪烁的一个亮块或一条竖线,如果在一个文字编辑的屏幕上就更好理解了,光标会随着键盘的上下左右键相应的移动。这个词在数据库查询的结果集中使用时就翻译成了游标,与光标的区别是它只能上下移动,代表在不同的数据行间选择。

在一条查询语句被执行后,就生成了一个结果集,这时游标处在第一行数据之前,所以取回(fetch)下一条数据(SQL_FETCH_NEXT)就是取回第一条数据。调用一次fetch函数,游标就停在fetch回的最后一条数据上,如果只取回一条,那么游标就在这条数据上,如果取回多条(使用数组取回),那么游标就停在最后一条数据上。

前面我们用到的SQLFetch()函数只能取回下一条数据,使用的是一种只能向前滚动的游标,如果要取回当前数据之前的某条数据就会比较麻烦,只能重新执行查询语句,然后再fetch到想要的那条数据,即浪费时间,有操作复杂。为解决这样的问题,ODBC提供了滚动游标(scrollable cursor),这种游标可以从任意位置取回结果集中的数据行。要使用滚动游标,需要设置语句属性SQL_ATTR_CURSOR_SCROLLABLE,属性值为SQL_SCROLLABLE,设置这个属性的位置有些特别,要在分配语句句柄后设置,在SQLPrepare()或SQLExecDirect()函数调用之前,否则会出错。

在执行语句后生成了结果集,这时就可以使用滚动游标了,取回数据的函数要使用SQLFetchScroll(),而不是SQLFetch()。我们看一下SQLFetchScroll()的函数原型和参数。

SQLRETURN SQLFetchScroll(
      SQLHSTMT        StatementHandle,
      SQLSMALLINT   FetchOrientation,
      SQLLEN              FetchOffset);

StatementHandle是一个输入参数,查询语句的句柄。

FetchOrientation是一个输入参数,取回数据的方向值。取值如下:

SQL_FETCH_NEXT(取下一条)
SQL_FETCH_PRIOR(取当前行的前一条)
SQL_FETCH_FIRST(取第一行)
SQL_FETCH_LAST(取最后一行)
SQL_FETCH_ABSOLUTE(按绝对行号取数据)
SQL_FETCH_RELATIVE(按相对行号取数据)
SQL_FETCH_BOOKMARK(按书签取数据)

FetchOffset是一个输入参数,取数据的行号偏移量。对于绝对行号取数据,偏移量就是某个行号,表示取结果集中的第几行。对于相对行号取数据,偏移量就是相对于当前行偏移几行,如果是正数,就是当前行加偏移行的行号,如果是负数,就是当前行减去偏移行的行号。

我们看一个实际的例子,怎样设置滚动游标属性,怎样使用SQLFetchScroll()函数。

#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                 i;
    int                 conn = 0;
    SQLRETURN           rc;
    SQLLEN              len_ind1;
    SQLLEN              len_ind2;
    SQLLEN              len_ind3;
    SQLLEN              len_ind4;
    SQLLEN              len_ind5;
    SQLINTEGER          id;
    char                dsn_str[32];
    char                usrname[32];
    char                passwd[32];
    char                sqltxt[128];
    char                f1[32];
    char                f2[32];
    char                f3[32];
    char                f4[32];


    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;
    }

    /* 设置结果集使用滚动游标 */
    rc = SQLSetStmtAttr(stmth, SQL_ATTR_CURSOR_SCROLLABLE,
        (SQLPOINTER)SQL_SCROLLABLE, 0);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Set statment attribute error.\n");
        goto free_exit;
    }

    /* 准备语句 */
    sprintf(sqltxt, "select id, f1, f2, f3, f4 from my_tredo1");
    rc = SQLPrepare(stmth, (SQLCHAR *)sqltxt, SQL_NTS);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Prepare statment error.\n");
        goto free_exit;
    }

    rc = SQLBindCol(stmth, 1, SQL_C_ULONG, (SQLPOINTER)&id, 0, &len_ind1);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Bind column 1 error.\n");
        goto free_exit;
    }

    rc = SQLBindCol(stmth, 2, SQL_C_CHAR, (SQLPOINTER)f1, 32, &len_ind2);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Bind column 2 error.\n");
        goto free_exit;
    }

    rc = SQLBindCol(stmth, 3, SQL_C_CHAR, (SQLPOINTER)f2, 32, &len_ind3);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Bind column 3 error.\n");
        goto free_exit;
    }

    rc = SQLBindCol(stmth, 4, SQL_C_CHAR, (SQLPOINTER)f3, 32, &len_ind4);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Bind column 4 error.\n");
        goto free_exit;
    }

    rc = SQLBindCol(stmth, 5, SQL_C_CHAR, (SQLPOINTER)f4, 32, &len_ind5);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Bind column 4 error.\n");
        goto free_exit;
    }

    rc = SQLExecute(stmth);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Execute statment error.\n");
        goto free_exit;
    }

    /* 先使用SQL_FETCH_NEXT参数,把结果集中的数据行都打印出来 */
    for (i=1; ;i++) {
        rc = SQLFetchScroll(stmth, SQL_FETCH_NEXT, 0);

        if (rc == SQL_NO_DATA) {
            fprintf(stderr, "no data in result set, break.\n");
            break;
        } else if (rc == SQL_ERROR) {
            fprintf(stderr, "Fetch data error.\n");
            goto free_exit;
        }

        fprintf(stdout, "row[%02d] id=%d, f1=%s, f2=%s, f3=%s, f4=%s\n",
            i, id, f1, f2, f3, f4);
    }

    /* 取回第一条数据,打印显示 */
    rc = SQLFetchScroll(stmth, SQL_FETCH_FIRST, 0);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Fetch the first row error.\n");
        goto free_exit;
    }

    fprintf(stderr, "The first row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n",
        id, f1, f2, f3, f4);

    /* 取回最后一条数据,打印显示 */
    rc = SQLFetchScroll(stmth, SQL_FETCH_LAST, 0);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Fetch the last row error.\n");
        goto free_exit;
    }

    fprintf(stderr, "The last row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n",
        id, f1, f2, f3, f4);

    /* 取回倒数第二行数据,打印显示 */
    rc = SQLFetchScroll(stmth, SQL_FETCH_PRIOR, 0);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Fetch the second to last row error.\n");
        goto free_exit;
    }

    fprintf(stderr, "The second to last row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n",
        id, f1, f2, f3, f4);

    /* 使用相对行号,取回倒数第二条的前一条,就是倒数第三行的数据 */
    rc = SQLFetchScroll(stmth, SQL_FETCH_RELATIVE, -1);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Fetch the third to last row error.\n");
        goto free_exit;
    }

    fprintf(stderr, "The third to last row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n",
        id, f1, f2, f3, f4);

    /* 使用绝对行号,取回第五行的数据 */
    rc = SQLFetchScroll(stmth, SQL_FETCH_ABSOLUTE, 5);
    if (rc != SQL_SUCCESS) {
        fprintf(stderr, "Fetch the fifth row error.\n");
        goto free_exit;
    }

    fprintf(stderr, "The fifth row:\nid=%d, f1=%s, f2=%s, f3=%s, f4=%s\n",
        id, f1, f2, f3, f4);

    /* 关闭游标 */
    SQLCloseCursor(stmth);

    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工具的源代码,学习高技术含量的内容。

ODBC API 学习总结 ODBC 编程API http://blog.youkuaiyun.com/bichenggui/article/details/5601381 转的ODBC API函数详细说明。 看了一遍,没有问题。 使用 ODBC API 之前要用到的头文件和 LIB 库  #include "sql.h"              // This is the the main inc 阅读详情

相关推荐

智能车视觉算法实战:十字路口与弯道拐点的精准识别

本文深入探讨了智能车视觉导航中十字路口与弯道拐点的精准识别算法。通过实战经验,详细解析了如何利用纵向巡线法生成边界数组,并从中高效提取“上拐点”与“下拐点”的关键特征。文章重点分享了提升算法鲁棒性的核心技巧,包括图像预处理、ROI设置、状态机应用及多特征融合,旨在帮助开发者实现智能车在复杂路况下从“看见”到“看懂”的稳定决策。

weixin_29061465的博客 633

Mysql使用SQLFetch()获取结果数据 - 基于 SQLBindCol

SQLFetch() 函数获取结果数据有三种方式: 1. 基于SQLBindCol 函数 2. 基于SQLGetData 函数 3.SQLBindCol 和 SQLGetData 函数结合。 基于SQLGetData 函数的方法参见: 目录 1. 参数简介 2. 代码示例: 2.1 示例 2.2 结果: 3. 其他C类型名称(不全,详情查看sqlext.h): 4. SQLBindCol 函数参数详细说明,摘自MSDN。 1. 参数简介 SQLRETURN SQLBind..

L946494的博客 2339

【Lane】 Ultra-Fast-Lane-Detection 复现

引言 车道线检测源码复现以及训练自己的数据集 1 环境搭建 conda create -n lane python=3.7 conda activate lane # 激活环境 conda install pytorch torchvision cudatoolkit=10.1 -c pytorch pip install -r requirements.txt 2 下载项目源码 若在服务器上可以用指令下载,否则直接在网址中下载 git clone https://github.com/cfzd/U

qq_44703886的博客 2万+

oracle滚动游标原理,Pro*C中的滚动游标(一)

在Pro*C中的滚动游标可以方便的获得当前记录的前面一条,后面一条,以及第一条、最后一条。很多开发人员一般采用如下的方法,循环FETCH 直到最后一条。while (1){fetch 游标名 into 变量列表;if (sqlca.sqlcode=1403) then break;}如果使用滚动游标,会更加方便获得最后一条。下面给出一个简单的例子SQL> SELECT EMPNO,ENAM...

weixin_42452483的博客 483

2025-03-21(DS复习): Databricks 的技术架构

Databricks 的技术架构以 ​为核心,构建了一套高度集成、可扩展且支持多云环境的统一分析平台。其架构设计注重存储与计算的深度融合,并通过丰富的服务层功能简化了数据工程、机器学习和数据科学的工作流。

baidu_24377669的博客 1427

别再傻傻分不清!5分钟搞懂倾斜摄影里‘地面分辨率’和‘模型精度’到底啥关系

本文深入解析倾斜摄影中‘地面分辨率’与‘模型精度’的关系,帮助读者快速理解两者的本质区别与内在关联。通过实战案例和公式计算,详细说明如何从航飞设计到精度验证全流程控制,避免常见认知误区,并针对不同应用场景提供精度需求建议。

weixin_33700350的博客 476

SQL中游标的使用

类型:   1.普通游标 只有NEXT操作   2.滚动游标 有多种操作 1.普通游标 DECLARE @username varchar(20),@UserId varchar(100) DECLARE cursor_name CURSOR FOR --定义游标 SELECT TOP 10 UserId,UserName FROM UserInfo ORDER BY UserId DESC OPEN cursor_name --打开游标 FETCH NEXT FROM c.

wozengcong的专栏 1万+

Qualcomm工具的使用

简介   由于我们公司主要是以高通平台为主,所以工具的使用是必不可少的,包括QPST、QRCT3、QXDM、QDART等。   高通工具顾名思义就是,对于高通平台的软件开发进行软件的烧录,软件的调试,软件的Log的抓取和分析过程,像我们平常用的大致就是烧版本、改NV、制作QCN、然后校准、强发强收等操作。 QPST   QPST主要是用来做一些参数的配置,包括EFS文件的编辑,QCN的导入和备份与...

Jimmy 2万+

存储过程,游标,sql过程,触发器,ODBC api

需要打开sql sever browser才可以搜索到服务器。

qq_46658082的博客 300

C# Socket通信从入门到精通(14)——多个异步UDP客户端C#代码实现(史上最全)

本文详细介绍了Socket通信中多个异步Udp客户端功能的实现、介绍如何使用多个客户端与多个服务器进行数据的交互,包含连接服务器、断开服务器、发送数据、读取数据、C#代码实现,由高级工程师多年经验总结而成,绝对干货!

qq_34059233的博客 1981

基于STM32XX的LCD液晶显示屏(HS280S010B、驱动芯片:ST7789V)驱动C程序设计

/ 16位/pixel (RGB565)#define LCD_WIDTH 240 // 屏幕宽度。#define LCD_HEIGHT 280 // 屏幕高度。LCD_ROTATION_180, // 180度旋转。LCD_ROTATION_270 // 270度旋转。LCD_ROTATION_90, // 90度旋转。LCD_ROTATION_0 = 0, // 0度旋转。

myron6688的博客 369

万级数据流畅滚动!虚拟列表+游标分页实战指南

在Web应用开发中,海量数据列表的渲染性能一直是前端工程师面临的重要挑战。传统的分页加载方式虽然能缓解部分压力,但在需要连续滚动的场景中(如社交信息流、电商商品列表),用户仍然会遭遇卡顿、白屏等问题。本文将深入解析我们如何通过虚拟列表(Virtual List)结合智能无限滚动(Infinite Scroll)技术,实现。的流畅渲染,并分享完整的前后端协作方案。

2401_86250490的博客 3507

杰理JL701N V142的SDK实现双备份自定义OTA教程和代码分享

摘要 本文档详细介绍了基于JL701N SDK的UART OTA升级功能开发方案。该方案采用双备份(Dual Bank)机制,通过串口实现安全可靠的固件远程更新。核心特性包括:1) 双备份升级机制确保升级失败可回滚;2) CRC-16/XMODEM校验保障数据完整性;3) 灵活的传输控制,支持自定义波特率和数据包大小。文档提供了完整的系统架构、API接口说明、通信协议规范以及移植指南,适用于生产烧录、现场升级等多种场景。配套Python升级工具简化了升级流程,使开发人员能够快速实现固件更新功能。

qq_42014563的博客 275

SQLSetStmtAttr

SQLSetStmtAttr函数定义:Stmt是用来执行SQL语句的句柄,这个函数是用来设置她的属性的SQLRETURN SQLSetStmtAttr(     SQLHSTMT     StatementHandle,     SQLINTEGER     Attribute,     SQLPOINTER     ValuePtr,     SQLINTEGER     StringLengt...

jadeshu的博客 2625

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

数据库常见面试题 —— 8. 游标 (CURSOR) 的定义、分类和使用

Oracle 游标的定义、分类、使用

gly1653810310的博客 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

ODBC Cursor

  http://msdn.microsoft.com/en-us/library/aa215458%28v=sql.80%29.aspx 写道 To set cursor options Call SQLSetStmtAttr to set or SQLGetStmtAttr to get the statement options that control cursor beha...

iteye_10111的博客 281

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

SQL用法三(游标和Fetch)

/一般情况下,我们用SELECT这些查询语句时,都是针对的一行记录而言,如果要在查询分析器中对多行记录(即记录集)进行读取操作时,则需要使用到游标或WHILE等循环/以下内容摘自http://www.cnblogs.com/aotian56/archive/2007/07/13/817281.html/游标的类型: 1、静态游标(不检测数据行的变化) 2、动态游标(反映所有数据行的改变) 3...

weixin_30260399的博客 1257

Pro*C中滚动游标的使用

#include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;stdlib.h&gt; #include &lt;sqlca.h&gt; void connect(); void sql_err();void cursor(); void main() { EXEC SQL WHENEVER SQLERROR ...

数据库天地 279

滚动游标失效(Rolling Cursor Invalidations)

在Oracle 10g中DBMS_STATS包针对GATHER_TABLE/INDEX_STATS和DELETE_TABLE/INDEX_STATS等收集统计信息的存储过程提供了AUTO_INVALIDATE选项; 该参数允许用户指定是否让那些对统计信息有依存关系的游标失效,举例来说如果SQL游标涉及到的表,索引,列或固有对象的统计信息收到以上存储过程修...

weixin_34403693的博客 367

使用ODBC访问数据库(一)

  使用ODBC访问数据库(一) 收藏 使用ODBC API之前要用到的头文件和LIB库#include "sql.h"              // This is the the main include for ODBC Core functions.#include "sqlext.h"         // This is the include for applications us

申公的专栏 1095

[Pro*c]滚动游标变量的使用

代码:xx.pc /* 功能:演示了Oracle滚动游标变量的使用 定义游标时注意事项: 1. DECLARE CURSOR语句必须是使用游标的第一条语句 2. 游标名称是一个标识符,而不是宿主变量,其长度是可以任意的,但只有前31个字

JoeBlackZQQ的专栏 1086

PRO*C 使用滚动游标

该文档拷贝与:http://blog.sina.com.cn/s/blog_7e3016270100yh67.html 该文档仅仅为了用于保存,留于以后查看,如有侵权,敬请谅解!! 1.使用非滚动游标 EXECSQL PREPARE SQL_STATEMENT FROM:statement; CheckSqlError("PREPARESQL_STATEMENT"); E

涯的博客 642

可滚动的游标记录集JDBC

  可滚动的游标记录集package text;import java.sql.Connection;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Statement;public class RollQuery {public sta

BLACK的专栏 1467

使用滚动游标作出定位更新

$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2'); // create a named, scrolling, updateable cursor $stmt = $db->prepare("select url, size from links FOR UPDATE OF size", array( PDO_ATTR_CURSOR => PDO

hyb0852的专栏 888
上一篇: unixODBC编程(七)数组查询
下一篇: unixODBC编程(九)分片查询长数据
tomcoding
博客等级 码龄9年 410粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值