LightDB pro*c迁移指南(游标模块)

文章目录

  • 一、不使用SQLDA描述符范围的游标操作
    • 1.1 oracle 案例
      • 1.1.1 使用游标获取数据
      • 1.1.2 对于fetch结果集怎么去利用
    • 1.2 LightDB 案例
      • 1.2.1 使用游标获取数据
      • 1.2.2 对于fetch结果集怎么去利用
    • 3 总结:不同项
  • 二、使用SQLDA描述符范围的游标操作
    • 2.1 Oracle样例
      • 2.1.1 使用SQLDA描述符范围的游标获取数据
    • 2.2 LightDB样例
      • 2.2.1 使用SQLDA描述符范围的游标获取数据
    • 3 总结:不同项
  • 三、总结

今天我们讲解的是关于pro*c迁移指南中的游标模块;这个模块我们分为两部分来讲:
(一)、不使用SQLDA描述符范围的游标操作
(二)、使用SQLDA描述符范围的游标操作
讲解方法主要为:oracle案例分析和LightDB案例分析,对比,列出不同点

一、不使用SQLDA描述符范围的游标操作

1.1 oracle 案例

1.1.1 使用游标获取数据

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct fetch_results
{
int a;
char b[10];
int c;
}fr;

int main() {
    EXEC SQL BEGIN DECLARE SECTION;
       char *uid ; //连接串信息自己补充
       int tmp;
       static fr arr[6];
    EXEC SQL END DECLARE SECTION;
    EXEC SQL CONNECT :uid;
    //连接是否成功
    if (sqlca.sqlcode == 0)
    	printf("是否成功连接:%d\n",sqlca.sqlcode);
    else
    {
   		 printf("是否成功连接:%d\n",sqlca.sqlcode);
    	return -1;
    }

	//声明游标
    exec sql declare cur cursor for select * from test;
	fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);

	//打开游标
    exec sql open cur;
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);
    
	//获取数据
    exec sql fetch cur into :arr;
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);
    printf("获取行数:%d\n", sqlca.sqlerrd[2]);
   
    //关闭游标
    exec sql fetch cur into :arr;
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);

  //断开连接
  EXEC SQL COMMIT WORK RELEASE
  exit(0);
}

上面给出的列子中,fetch获取结果集的行数,我们可以通过sqlca.sqlerrd[2]来确定,oracle中sqlca.sqlerrd[2]被用来记录获取的结果集的行数
我们发现sqlca.sqlerrd[2]的值刚好与arr数组的大小是相等,随着arr数组的大小的变动sqlca.sqlerrd[2]也会变动。

1.1.2 对于fetch结果集怎么去利用

这里我们用打印的方式进行显示

    while (1)
    {
      exec sql fetch cur into :arr;  
      Rows = sqlca.sqlerrd[2] - DealRows;
      for (i=0;i<Rows;i++)  
      { 
        printf("a:%d,b:%s,c:%d", arr[i].a,arr[i].b,arr[i].c);
      }	     	    
      DealRows = sqlca.sqlerrd[2];  
      if (sqlca.sqlcode==1403)
      {
          iFetchCount=sqlca.sqlerrd[2];
          break;
       }
     }

上述程序需要稍加解析:我们添加了三个变量去完成这个算法;分别为Rows、DealRows、iFetchCount。它们代表的意思如下:
Rows:这次fetch获取的行数;
DealRows:已经获取的行数
iFetchCount:获取总行数;
为什么我们会多此一举在这里使用三个变量进行运算哪?
这是有使用场景决定的,当我们查询的结果集的长度超出了我们目标的数组大小(获取的实际长度为目标数组的大小),就需要用到上面这段代码了。还需要再强调一次,oracle中sqlca.sqlerrd[2]被用来记录获取的结果集的行数。
好的,知道了这些我们再来看代码
Rows = sqlca.sqlerrd[2] - DealRows; Rows等于总行数 - 已经获取过的结果集行数;
DealRows = sqlca.sqlerrd[2]; 已经获取过的结果集行数;
**iFetchCount=sqlca.sqlerrd[2];**最后判断no_data_found,获得fetch总行数。

1.2 LightDB 案例

1.2.1 使用游标获取数据

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct fetch_results
{
int a;
char b[10];
int c;
}fr;

int main() {
    Test_cf cf ;
    EXEC SQL BEGIN DECLARE SECTION;
       char *uid ; //连接串信息自己补充
       int tmp;
       static aa1_a arr[6];
    EXEC SQL END DECLARE SECTION;
    EXEC SQL CONNECT :uid;
    //连接是否成功
    if (sqlca.sqlcode == 0)
    	printf("是否成功连接:%d\n",sqlca.sqlcode);
    else
    {
   		 printf("是否成功连接:%d\n",sqlca.sqlcode);
    	return -1;
    }

	//声明游标
    exec sql declare cur cursor for select * from test;
	fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);

	//打开游标
    exec sql open cur;
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);
    
	//获取数据
    exec sql fetch cur into :arr;
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);
    printf("获取行数:%d\n", sqlca.sqlerrd[2]);
   
    //关闭游标
    exec sql fetch cur into :arr;
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);

  //断开连接
  EXEC SQLdisconnect;
  exit(0);
}

对比发现,与oracle存在两个不同点:
(1)断开连接不同;
(2)LightDB fetch into 语法只能获取一行,不是由目标数组的大小决定的
因此我们在对于fetch结果集怎么去利用的方法肯定不一致

1.2.2 对于fetch结果集怎么去利用

这里我们用打印的方式进行显示

  while (1)
  {
    exec sql fetch 6 cur into :arr;  
    iFetchCount += sqlca.sqlerrd[2];
    Rows = sqlca.sqlerrd[2];
    for (i=0;i<Rows;i++)
    {
        printf("a:%d,b:%s,c:%d", arr[i].a,arr[i].b,arr[i].c);
    }
   DealRows =  iFetchCount;
    if ( sqlca.sqlcode==ECPG_NOT_FOUND)
    {
      break;
    }
  }

我们发现虽然代码看起来差不多,但是却存在3个细节上的差异:
(1)fetch into变成了fetch count into,为了兼容oracle其长度设置成oraclearr数组的长度,即可;
(2)添加的变量一样,但是算法发生了变化:
Rows = sqlca.sqlerrd[2]; 当前获取的行数;
DealRows = iFetchCount; 已经获取的行数;
iFetchCount += sqlca.sqlerrd[2]; 获取的总行数;
(3)no_data_found的错误码不一致了,LightDB返回的错误码为100,oracle返回的错误码为1403

3 总结:不同项

(1)fetch into获取的长度不一样;导致获取字段结果的算法不一致;
(2)错误码不一样
(3)断开连接的方式不一样(关于连接有空再单独介绍)

二、使用SQLDA描述符范围的游标操作

这一章我们会在不使用SQLDA描述符范围的游标操作的基础上进行讲解。
我们需要对于使用SQLDA描述符范围的游标操作,给一个总体的介绍
test
在使用SQLDA描述符范围游标的过主要分为两部分。查询的目标列表和绑定两部分。

2.1 Oracle样例

2.1.1 使用SQLDA描述符范围的游标获取数据

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h>
#include <sqlda.h>

int main() {
{ 
	char sqlstr[1000] = "select * from test";
    EXEC SQL PREPARE DYSQLSA FROM :sqlstr;

    EXEC SQL DECLARE Cursorbase CURSOR FOR DYSQLSA;
    
    EXEC SQL DESCRIBE BIND VARIABLES for DYSQLSA INTO BindUnit;

    for (i = 0 ; i < BindUnit->N; i++)
    { 
        //这里设置L、V、I、T等类型
    }

    EXEC SQL OPEN Cursorbase USING DESCRIPTOR BindUnit;

    EXEC SQL DESCRIBE SELECT LIST for DYSQLSA INTO SelectUnit;

    for (i=0; i < SelectUnit->F; i++)
    {
        //这里设置L、V、I、T等
        switch (type)
        { 
            //类型处理
        }      
    }

    for(;;)
    { 
        EXEC SQL FOR :array_size FETCH Cursorbase USING DESCRIPTOR SelectUnit;

        for (j = 0 ;j < sqlca.sqlerrd[2] - iRowCount; j ++)
        {
            for (i=0; i < SelectUnit->F; i++)
            { 
                //对每个字段进行处理
            }  
        }
        iRowCount = sqlca.sqlerrd[2];
        if (sqlca.sqlcode == 1403) 
            break;   
    } 

    EXEC SQL commit;
    EXEC SQL CLOSE cur; 
}

我们需要说明一下几点:
(1)EXEC SQL DESCRIBE BIND VARIABLES for DYSQLSA INTO BindUnit; DESCRIBE 已将 F 设置为已处理 SQL 语句中找到的占位符的实际数量。
这个BindUnit主要针对需要绑定的变量:
举个例:
select * from test;这个查询语句就不存在需要绑定的变量,因此不需要对BindUnit进行设置;
select * from test where a := :var;这就涉及到对描述符进行赋值部分oracle 官方sqlda
(2)相较于不使用SQLDA描述符范围的游标操作,在打开游标时我们会使用到SQLDA描述符范围:
EXEC SQL OPEN Cursorbase USING DESCRIPTOR BindUnit;
(3) EXEC SQL DESCRIBE SELECT LIST for DYSQLSA INTO SelectUnit; DESCRIBE 已将 F 设置为查询选择列表中的实际项数。如果 SQL 语句不是查询,则 F 设置为零。
(4) EXEC SQL FOR :array_size FETCH Cursorbase USING DESCRIPTOR SelectUnit; for :arrary_size指定获取的行数;
(5)释放游标的过程为:

    EXEC SQL commit;
    EXEC SQL CLOSE cur; (commit提交之后并不影响close游标)。

2.2 LightDB样例

2.2.1 使用SQLDA描述符范围的游标获取数据

针对上面的程序,LightDB目前采用的方案主要是改写。
改写的主要内容分为:
(1) SQLDA类型不支持,需要替换成sqlda_t

sqlda_t *SelectUnit ; 
sqlda_t *BindUnit; 

(2)EXEC SQL OPEN Cursorbase USING DESCRIPTOR BindUnit; 部分改写;

            if (是否有绑定参数)
              EXEC SQL EXECUTE ExecSQLs USING SQL DESCRIPTOR indesc;
            else
              EXEC SQL EXECUTE ExecSQLs;  

原因:LightDB不支持没有绑定参数的使用SQLDA描述符范围
(3)EXEC SQL DESCRIBE BIND VARIABLES for DYSQLSA INTO BindUnit;

            for ( j = 0 ; j < sqlpkg->paramcount; j ++)
            {
               BindUnit->sqlvar[j].sqldata = (char *)malloc(sqlpkg->params[j].val.data_size+1);  
               memcpy(BindUnit->sqlvar[j].sqldata, sqlpkg->params[j].val.data, sqlpkg->params[j].val.data_size );
               BindUnit->sqlvar[j].sqldata[sqlpkg->params[j].val.data_size] = '\0';
               BindUnit->sqlvar[j].sqltype = 1; 
               BindUnit->sqlvar[j].sqllen  = val.data_size;
               BindUnit->sqln = sqlpkg->paramcount;
            }

(4) EXEC SQL DESCRIBE SELECT LIST for DYSQLSA INTO SelectUnit; 语法是不支持的,这部分在LightDB中是由内核完成的

(5) EXEC SQL FOR :array_size FETCH Cursorbase USING DESCRIPTOR SelectUnit; 语法是不支持的,但是可以通过fetch into解决获取行数的问题

 EXEC SQL FETCH :array_size CursorbaseSuper INTO DESCRIPTOR SelectUnit;

(6) commit和close执行位置问题,LightDB只支持先close后commit

    EXEC SQL CLOSE cur; 
    EXEC SQL commit;

3 总结:不同项

(1)SQLDA类型不支持
(2)EXEC SQL OPEN Cursorbase USING DESCRIPTOR BindUnit使用时有条件限制
(3)EXEC SQL DESCRIBE BIND VARIABLES for DYSQLSA INTO BindUnit;语法不支持
(4)EXEC SQL DESCRIBE SELECT LIST for DYSQLSA INTO SelectUnit;语法不支持
(5)EXEC SQL FOR :array_size FETCH Cursorbase USING DESCRIPTOR SelectUnit;不支持
(6)commit和close执行位置问题
隐藏不支持项,在于对各个绑定或者获取字段时其类型的转化是有差别的,以及在第一部分出现的不支持项,在这部分依旧是不支持项。

三、总结

针对所列举的不支持项,LightDB目前正在全力适配中,相信不久之后上述问题就能解决。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于java的CRM客户关系管理系统(五)

目录 第五章 系统的详细设计与实现 5.1 持久层设计 5.1.1 创建关系映射 5.1.2 与数据库的连接 5.1.3 Hibernate的ORM映射 5.1.4 Struts的配置文件 5.1.5 Spring 的配置文件 5.1.6 DAO层设计 5.2 逻辑业务层设计 5.2.1 业务逻辑类的实现 前面内容请移步 基于java的C…

Jmeter干货分享:当你的Log viewer不显示日志时,可能是引入的Jar包冲突导致

问题描述 近期使用Jmeter时发现了一个非常奇怪的问题&#xff0c;就是Jmeter是可以正常使用运行脚本&#xff0c;但是在Log viewer中确没有任何日志&#xff0c;如下图&#xff1a; 问题排查过程 真是百思不得其解啊&#xff0c;在网上各种获取资料&#xff0c;大多数都是说跟…

001----flask

flask---001 flask与django对比今日概要问答今日详细1.flask快速使用1.2 快速使用flask1.3 用户名密码登录 flask与django对比 django是个大而全的框架&#xff0c;flask是一个轻量级的框架。 django内部为我们提供了非常多的组件&#xff1a;orm/session/cookie/admin/from/mo…

【学习】企业如何选择一个合适的DCMM咨询机构

DCMM是我国首个数据管理领域正式发布的国家标准。旨在帮助企业利用先进的数据管理理念和方法&#xff0c;建立和评价自身数据管理能力&#xff0c;持续完善数据管理组织、程序和制度&#xff0c;充分发挥数据在促进企业向信息化、数字化、智能化发展方面的价值。该标准借鉴了国…

Python学习从0开始——Kaggle机器学习003总结

Python学习从0开始——Kaggle机器学习003总结 一、加载及浏览数据二、机器学习模型三、模型验证四、欠拟合和过拟合五、随机森林 一、加载及浏览数据 # 路径 melbourne_file_path ../input/melbourne-housing-snapshot/melb_data.csv # 读取 melbourne_data pd.read_csv(mel…

为什么大家都要考CDA数据分析师认证

为什么学习数据分析&#xff1f; 2024年&#xff0c;是一个被数据影响的时代。数据&#xff0c;如同无形的燃料&#xff0c;驱动着现代社会的运转。从全球互联网的用户每天产生的2.5亿TB数据&#xff0c;到制造业的传感器、金融交易、医疗病历等领域的海量信息&#xff0c;数据…

排序算法——归并排序以及非递归实现

一、归并排序思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列…

使用Python绘制瀑布图

使用Python绘制瀑布图 瀑布图效果代码 瀑布图 瀑布图&#xff08;Waterfall Chart&#xff09;是一种数据可视化工具&#xff0c;用于展示累积数值的变化&#xff0c;尤其适合于展示随时间或过程中的增减变化。它通常用于财务分析&#xff0c;如展示收入、支出和净利润的变化过…

分离式光电液位传感器与浮球开关相比具有哪些优势

分离式光电液位传感器与浮球开关相比有哪些优势&#xff1f;分离式光电液位传感器依据光学原理&#xff0c;在传统光学传感器的基础上进行了改进。其特点是将光学组件分离出来&#xff0c;置于水箱外部感应&#xff0c;而传感器本身则独立于水箱外。这种设计有效解决了浮球开关…

CPU内部结构窥探·「1」

CPU内部逻辑运算单元是如何运行的 引言 中央处理器&#xff08;CPU&#xff09;是计算机的大脑&#xff0c;负责处理各种计算任务。在CPU里面&#xff0c;有一个重要的部分叫做逻辑运算单元&#xff08;ALU&#xff0c;Arithmetic Logic Unit&#xff09;。ALU就像一个超级计…

JS面试题:hash和history的区别

一、hash 模式和 history 模式的介绍 由于 Vue 项目为单页面应用&#xff0c;所以整个项目在开发和构建过程中&#xff0c;仅存在一个HTML物理文件。通过路由系统可以实现将项目的组件与可访问的URL路径进行绑定。由于Vue项目只有一个HTML物理文件&#xff0c;切换页面时既需要…

vivado BD_INTF_NET、BD_INTF_PIN

BD_INTF_NET 描述 接口是一组信号&#xff0c;它们共享一个共同的功能&#xff0c;同时包含 单个信号和多条总线。例如&#xff0c;AXI4Lite主机包含一个 单个信号的数量加上多条总线&#xff0c;这些都是制作 联系通过将这些信号和总线分组到一个接口中&#xff0c;Vivado IP积…

VisualStudio中:如果某个项目不显示SVN的show log等,而其他项目都正常

VisualStudio中&#xff1a;如果某个项目不显示SVN的show log等&#xff0c;而其他项目都正常。说明大概率是当前项目的问题&#xff0c;而不是VisualStudio的问题&#xff01; 1.这个项目内有一个“隐藏”文件夹.svn 》先删除&#xff01; 2.如果外层文件夹有红色感叹号&…

英伟达剧透新一代最强 GPU;奥特曼公开回应 AI 语音争议丨 RTE 开发者日报 Vol.217

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」&#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

重学java 59.Properties属性集集合嵌套集合下总结

不要咀嚼小小悲观&#xff0c;而忘掉整个世界 —— 24.6.3 一、Properties集合&#xff08;属性集&#xff09; 1.概述 Properties 继承 于HashTable 2.特点 a、key唯一&#xff0c;value可重复 b、无序 c、无索引 d、线程安全 e、不能存null键&#xff0c;null值 f、Propertie…

idea项目maven下载依赖报错

报错&#xff1a; 1、Failure to find bad.robot:simple-excel:jar:1.0 in https://maven.aliyun.com/repository/public was cached in the local repository, resolution will not be reattempted until the update interval of aliyunmaven has elapsed or updates are forc…

小程序集arcgis地图显示自定义坐标的功能实现记录!(学习笔记)

最近再做一个新能源回收项目&#xff0c;项目中有个根据回收点坐标数据显示区域内回收点位置&#xff0c;点击图标直接导航到该位置&#xff0c;及分布的需求&#xff0c;研究了一下&#xff0c;实现效果如下&#xff0c;实现起来很简单&#xff0c;代码及效果 回收点位置及分…

Linux - 逻辑卷的创建和管理

1.逻辑卷LVM的创建 1.1 创建步骤 ①添加硬盘或者创建分区 ②创建物理卷 pvcreate ③创建卷组 vgcreate ④创建逻辑卷 lvcreate ⑤创建文件系统 mkfs.xfs/ect4/... ⑥创建挂…

随身wifi哪个牌子的最好用?网速最快的随身wifi推荐测评,随身wifi罗永浩推荐!

现在很多人都开始使用随身WiFi&#xff0c;因为互联网发达&#xff0c;看视频、刷抖音、看直播等等都需要流量&#xff0c;手机流量不够用&#xff0c;流量需求也很高。因此随身WiFi逐渐出现在人们的视野中&#xff0c;在众多品牌中一款名为格行的随身wifi被各明星和千万网红争…

Docker基础篇之本地镜像发布到阿里云

文章目录 1. 本地镜像发布到阿里云的流程2. 阿里云开发平台3. 将自己的本地镜像推送到阿里云 1. 本地镜像发布到阿里云的流程 阿里云ECS Docker生态如下图所示&#xff1a; 2. 阿里云开发平台 在控制台找到容器和镜像服务&#xff1a; 然后创建一个个人实例&#xff1a; 下面…