第1关:ODBC程序设计

news2024/11/26 14:53:47

第1关:ODBC程序设计

    • 任务描述
    • 相关知识
    • ODBC主要功能
    • ODBC接口主要函数
    • ODBC应用程序开发实例
      • DM ODBC应用程序开发总体流程
      • DM ODBC代码编写流程
      • DM ODBC代码编写实例
    • 编程要求
    • 测试说明
    • 代码参考:

任务描述

本关任务:使用 ODBC 查询表中数据。

相关知识

为了完成本关任务,你需要掌握:
1.ODBC 的主要功能;
2.ODBC 接口主要函数;
3.ODBC 应用程序开发实例。

ODBC主要功能

ODBC(Open Database Connectivity,开放式数据库连接)是由 Microsoft 开发和定义的一种访问数据库的应用程序接口,其定义了访问数据库API的一组规范,这些API独立于形色各异的数据库系统和编程语言。因此,ODBC 支持不同编程语言,同时也支持不同的数据库系统。借助 ODBC 接口,应用程序能够使用相同的源代码和各种各样的数据库交互。这使得应用程序开发人员不需要考虑各类数据库系统的构造细节,只要使用相应 ODBC 驱动程序,即可通过将 SQL 语句发送到目标数据库中,可以访问和操作各类数据库中的数据。

也就是说,一个基于 ODBC 的应用程序,对数据库的操作不依赖任何数据库系统,所有的数据库操作由对应数据库的ODBC驱动程序完成。不论是 SQL Server、Access、Oracle,还是 DM 数据库,均可借助 ODBC API 进行访问。ODBC 体系结构如下图所示,ODBC 驱动程序管理器用于管理各种 ODBC 驱动程序,基于 ODBC 开发的应用程序通过 ODBC 驱动程序管理器,调用针对不同数据库的驱动程序,进行数据对象的维护、数据的查询和修改等操作。

DM8 数据库提供的 DM ODBC 3.0 接口遵照 Microsoft ODBC 3.0 规范设计与开发,实现了 ODBC 应用程序与 DM 的互连。其由 C 语言编写,其底层调用 DM DCI 接口实现。因此,应用程序开发人员可基于 ODBC 接口规范,使用 DM ODBC 驱动访问和操作 DM8 数据库。
,

ODBC接口主要函数

由于 DM ODBC 遵照 Microsoft ODBC 3.0 规范设计与开发,因此 DM ODBC 接口提供的函数与标准 ODBC 一致。由于 DM ODBC 接口函数较多,下图仅列出了 DM ODBC 接口的主要函数。

,

,

,

,

ODBC应用程序开发实例

DM ODBC应用程序开发总体流程

DM ODBC 为程序员提供了基于 ODBC 接口开发应用程序的手段,程序员使用 DM ODBC 开发应用程序时总体流程如下图所示。首先,安装 DM ODBC 驱动;其次,配置 ODBC 数据源;最后,基于 DM ODBC 编程规范,编写代码访问和操作 DM8 数据库。
,

1)安装 DM ODBC 驱动程序;
示例:
1.将附件 unixODBC-2.3.0.tar.gz 上传到 /usr/local 下,执行安装。

[root@localhost local]# tar -xzvf unixODBC-2.3.0.tar.gz
[root@localhost unixODBC-2.3.0]# cd unixODBC-2.3.0
[root@localhost unixODBC-2.3.0]# ./configure --enable-gui=no
[root@localhost unixODBC-2.3.0]# make
[root@localhost unixODBC-2.3.0]# make install

2.查看操作系统上查看 ODBC 版本

[dmdba@localhost]# odbc_config --version
2.3.0

3.查看 ODBC 配置文件存放的位置

[root@localhost etc]# odbc_config --odbcini
/etc/odbc.ini
[root@localhost etc]# odbc_config --odbcinstini
/etc/odbcinst.ini

4.修改odbc.ini文件

[dmdba@localhost]# vi /etc/odbc.ini
[dm]
Description = DM ODBC DSN
Driver = DM7 ODBC DRIVER
SERVER = localhost
UID = SYSDBA
PWD = SYSDBA
TCP_PORT = 5236

5.修改odbcinst.ini文件

[dmdba@localhost]# vi /etc/odbcinst.ini
[DM7 ODBC DRIVER]
Description = ODBC DRIVER FOR DM7
Driver = /opt/dmdbms/bin/libdodbc.so

6.测试连接

[root@localhost]# isql dm SYSDBA SYSDBA
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+

出现上述“Connected”就代表安装成功。

2)配置 DM ODBC 数据源;
3)编写 DM ODBC 代码。

DM ODBC代码编写流程

DM ODBC 数据源配置成功后,即可编写代码访问和操作数据库。遵循 ODBC 编程规范,基于 DM ODBC 接口编写代码访问和操作数据库大致流程如下图所示。

,

首先,创建连接环境和连接数据库。主要通过调用相关函数分配环境句柄、设置环境属性、分配连接句柄和建立数据库连接等过程。
其次,访问和操作数据库。主要通过建立的连接来分配语句句柄、执行SQL语句等操作,该过程是操作数据库的主体部分,与数据库的所有交互均在该过程完成。

最后,断开连接和释放连接资源。数据库操作完成后,程序需关闭数据库连接,并释放连接资源。

DM ODBC代码编写实例

【例1】 基于 DM ODBC 编程接口,利用已配置的 DM ODBC 数据源 DM,编写程序,实现获取数据源 DM 对应数据库中 DMHR.EMPLOYEE 表的数据,包括职员 ID、姓名、手机号码等信息。

在 Visual Studio Code 集成开发环境中,创建一个项目,并为项目添加一个 .cpp 源代码文件;然后添加依赖文件“dodbc.so”和达梦数据库安装目录下的 bin 和 include 两个依赖目录;接着基于 DM ODBC 接口编写代码。

1)创建连接环境和连接数据库

应用程序与 DM 数据库进行通讯,需要和数据库建立连接。①调用函数 SQLAllocHandle 申请环境、连接句柄;②调用函数 SQLSetEnvAttr 设置环境句柄属性;③调用函数 SQLSetConnectAttr 设置连接句柄属性;⑤调用连接函数 SQLConnect、SQLDriverConnect 或 SQLBrowseConnect 连接数据源。

2)访问和操作数据库

与 ODBC 数据源建立连接后,即可通过 ODBC 函数访问和操作数据。调用 SQLAllocHandle 申请语句句柄,通过该句柄执行 SQL 语句;调用函数 SQLPrepare 对 SQL 语句和操作进行准备;调用 SQLDescribeCol、SQLDescribeParam 等函数取得相关的描述信息,依据描述信息调用 SQLBindCol、SQLBindParam 等函数绑定相关的列和参数;调用 SQLExecute 执行 SQL 语句,实现相关的 SQL 操作。应用程序也可以调用 SQLExecDirect 直接执行 SQL 语句进行相关的 SQL 操作。

3)断开数据连接和释放连接资源

数据库操作完成后,程序需关闭数据库连接,并释放连接资源。如果要终止客户程序与服务器之间的连接,客户程序应当完成以下的几个操作:
(1)调用 SQLFreeHandle 释放语句句柄,关闭所有打开的游标,释放相关的语句句柄资源(在非自动提交模式下,需事先提交当前的事务);
(2)调用函数 SQLDisconnect 关闭所有的连接;
(3)调用 SQLFreeHandle 释放连接句柄及其相关的资源;
(4)调用 SQLFreeHandle 释放环境句柄及其相关的资源。

例 1 代码如下所示,该代码可用于查询 dmhr.employee 表中所有职工姓名、id 和电话号码。

#include <sys/socket.h> 
#include <unistd.h>
#include <stdio.h>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
/* 检测返回代码是否为成功标志,当为成功标志返回 TRUE,否则返回 FALSE */
#define RC_SUCCESSFUL(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO)
/* 检测返回代码是否为失败标志,当为失败标志返回 TRUE,否则返回 FALSE */
#define RC_NOTSUCCESSFUL(rc) (!(RC_SUCCESSFUL(rc)))
HENV henv; /* 环境句柄 */
HDBC hdbc; /* 连接句柄 */
HSTMT hsmt; /* 语句句柄 */
SQLRETURN sret;/* 返回代码 */
char szpersonid[11]; /*人员编号*/
SQLLEN cbpersonid=0;
char szname[51]; /*人员姓名*/
SQLLEN cbname=0;
char szphone[26]; /*联系电话*/
SQLLEN cbphone=0;
void main(void)
{
    /* 申请一个环境句柄 */
    SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
    if(henv == NULL){
        printf("ODBC 环境句柄分配失败");
        return;
    }
    /* 设置环境句柄的 ODBC 版本 */
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
    /* 申请一个连接句柄 */
    SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
    if(hdbc == NULL){
        printf("ODBC 连接句柄分配失败");
        return;
    }
    sret=SQLConnect(hdbc, (SQLCHAR *)"DM", SQL_NTS, (SQLCHAR *)"DMHR", SQL_NTS, (SQLCHAR *)"dameng123", SQL_NTS);
    if(sret == SQL_SUCCESS||sret==SQL_SUCCESS_WITH_INFO){
        /* 申请一个语句句柄 */
        SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hsmt);
        /* 立即执行查询人员信息表的语句 */
        SQLExecDirect(hsmt, (SQLCHAR *)"SELECT employee_id, employee_name, phone_num FROM dmhr.employee;", SQL_NTS);
        /* 绑定数据缓冲区 */
        SQLBindCol(hsmt, 1, SQL_C_CHAR, szpersonid, sizeof(szpersonid), &cbpersonid);
        SQLBindCol(hsmt, 2, SQL_C_CHAR, szname, sizeof(szname), &cbname);
        SQLBindCol(hsmt, 3, SQL_C_CHAR, szphone, sizeof(sazphone), &cbphone);
        /* 取得数据并且打印数据 */
        printf("人员编号 人员姓名 联系电话\n");
        for (;;) {
            sret = SQLFetchScroll(hsmt, SQL_FETCH_NEXT, 0);
            if (sret == SQL_NO_DATA_FOUND)
            break;
            printf("%s %s %s\n", szpersonid, szname, szphone);
        }
    }
    else{
            printf("连接失败\n");
        }
    /* 关闭游标,终止语句执行 */
    SQLCloseCursor(hsmt);
    /* 释放语句句柄 */
    SQLFreeHandle(SQL_HANDLE_STMT, hsmt);
    /* 断开与数据源之间的连接 */
    SQLDisconnect(hdbc);
    /* 释放连接句柄 */
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    /* 释放环境句柄*/
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
}

其中 DMHR 为用户名,dameng123 为密码。

编程要求

使用右侧 VS CODE 编写 ODBC 程序,查询 test.tb_class 表中所有数据。

登录用户名为:SYSDBA;密码:SYSDBA。

操作步骤:
1.打开 VS CODE,在 HELLOWORLD 项目下方新建 test.cpp 文件,并在该文件中实现 ODBC 程序需求;
2.编辑 HELLOWORLD 项目下的 task.json 文件,按下图所示添加依赖文件dodbc.so。
,

4.选中 test.c 文件,按下“Ctrl+Shift+B”,编译 test.cpp 文件;
5.点击测评。

test.tb_class 表字段信息:

字段名字段类型
idint
namevarchar(25)

测试说明

平台会对你编写的代码进行测试。


开始你的任务吧,祝你成功!

代码参考:

  1. 打开 VS CODE,编辑 HELLOWORLD 项目下的 task.json 文件,加上代码:“-dodbc”,
    路径参考
  2. 在 HELLOWORLD 项目下方新建 test.cpp 文件,复制以下代码:
    (点击右侧的 “工具栏”->“复制粘贴” 即可粘贴进去了)
    复制示例
#include <sys/socket.h> 
#include <unistd.h>
#include <stdio.h>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
/* 检测返回代码是否为成功标志,当为成功标志返回 TRUE,否则返回 FALSE */
#define RC_SUCCESSFUL(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO)
/* 检测返回代码是否为失败标志,当为失败标志返回 TRUE,否则返回 FALSE */
#define RC_NOTSUCCESSFUL(rc) (!(RC_SUCCESSFUL(rc)))
HENV henv; /* 环境句柄 */
HDBC hdbc; /* 连接句柄 */
HSTMT hsmt; /* 语句句柄 */
SQLRETURN sret;/* 返回代码 */
int szpersonid; /*人员编号*/
SQLLEN cbpersonid=0;
char szname[51]; /*人员姓名*/
SQLLEN cbname=0;
int main(void)
{
    /* 申请一个环境句柄 */
    SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
    if(henv == NULL){
        printf("ODBC 环境句柄分配失败");
        return -1;
    }
    /* 设置环境句柄的 ODBC 版本 */
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
    /* 申请一个连接句柄 */
    SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
    if(hdbc == NULL){
        printf("ODBC 连接句柄分配失败");
        return -1;
    }
    sret=SQLConnect(hdbc, (SQLCHAR *)"DM", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS);
    if(sret == SQL_SUCCESS||sret==SQL_SUCCESS_WITH_INFO){
        /* 申请一个语句句柄 */
        SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hsmt);
        /* 立即执行查询人员信息表的语句 */
        SQLExecDirect(hsmt, (SQLCHAR *)"SELECT id, name FROM test.tb_class;", SQL_NTS);
        /* 绑定数据缓冲区 */
        SQLBindCol(hsmt, 1, SQL_C_CHAR, &szpersonid, sizeof(szpersonid), &cbpersonid);
        SQLBindCol(hsmt, 2, SQL_C_CHAR, szname, sizeof(szname), &cbname);
        /* 取得数据并且打印数据 */
        for (int i = 1;;++i) {
            sret = SQLFetchScroll(hsmt, SQL_FETCH_NEXT, 0);
            if (sret == SQL_NO_DATA_FOUND)
            break;
            printf("%d %s\n", i, szname);
        }
    }
    else{
            printf("连接失败\n");
        }
    /* 关闭游标,终止语句执行 */
    SQLCloseCursor(hsmt);
    /* 释放语句句柄 */
    SQLFreeHandle(SQL_HANDLE_STMT, hsmt);
    /* 断开与数据源之间的连接 */
    SQLDisconnect(hdbc);
    /* 释放连接句柄 */
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    /* 释放环境句柄*/
    SQLFreeHandle(SQL_HANDLE_ENV, henv);

    return 0;
}

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

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

相关文章

Seata分布式事务实战

目录 1 Seata1.1 Seata术语1.2 Seata AT模式1.2.1 AT模式及工作流程1.2.2 Seata-Server安装1.2.3 集成springcloud-alibaba 1.3 Seata TCC模式 2 Seata注册中心2.1 服务端注册中心配置2.2 客户端注册中心配置 3 Seata高可用 1 Seata Seata实现分布式事务基础知识:https://blog.…

“敏捷”又“精益”的新企架思想,如何指导项目实施?

就像“一千个读者眼中有一千个哈姆雷特”&#xff0c;企业也有一千种被看待的方式&#xff0c;例如消费者会用品牌和产品来描述企业&#xff1b;投资者会用盈利模式和盈利空间来评估企业&#xff0c;而“企业架构”则是企业管理者、架构师等用来精确描述企业的方式。 通过业务…

【C语言】语言篇——程序设计入门

C站的小伙伴们大家好呀&#xff01;我最近在学习刘汝佳老师的《算法竞赛入门经典》&#xff0c;跟着这本书来学习和做习题&#xff0c;在这里和大家一起分享进步。下面是本书的第一部分的语言篇。 语言篇——程序设计入门 算术表达式变量及其输入顺序结构程序设计分支结构程序设…

1.1 什么是eBPF?(上)

大多数介绍eBPF的文章都是用“eBPF是一种革命性的内核技术”来描绘的。这样讲一点也不夸张。因为它允许在Linux的内核中执行沙盒程序,在不改变内核源码或加载内核模块的前提下直接地,安全地,快捷地扩展内核,并改变内核的行为。可以想像在运行时,将用户空间的eBPF程序加载到…

C4D R26 渲染学习笔记 建模篇(2):手动建模

介绍篇 C4D R26 渲染学习笔记&#xff08;1&#xff09;&#xff1a;C4D版本选择和初始UI框介绍 C4D R26 渲染学习笔记&#xff08;2&#xff09;&#xff1a;渲染流程介绍 C4D R26 渲染学习笔记&#xff08;3&#xff09;&#xff1a;物体基本操作快捷键 建模篇 C4D R26 渲…

第一个servlet的程序

文章目录 一.Hello World的程序1.创建项目2.引入依赖3.创建目录4.编写代码5.打包程序6.部署程序7.验证程序 二.简化部署方式1.下载插件2.配置smart Tomcat插件3.测试插件 三.常见的servelt问题出现 404出现 405出现 500出现 "空白页面"出现 "无法访问此网站&quo…

图像风格迁移

一、简介 图像风格迁移是指&#xff0c;将一副内容图的内容&#xff0c;和一幅或多幅风格图的风格融合在一起&#xff0c;从而生成一些有意思的图片。 我们使用 TensorFlow 和 Keras 分别来实现图像风格迁移&#xff0c;主要用到深度学习中的卷积神经网络&#xff0c;即CNN。…

Transformer应用之构建聊天机器人(二)

四、模型训练解析 在PyTorch提供的“Chatbot Tutorial”中&#xff0c;关于训练提到了2个小技巧&#xff1a; 使用”teacher forcing”模式&#xff0c;通过设置参数“teacher_forcing_ratio”来决定是否需要使用当前标签词汇来作为decoder的下一个输入&#xff0c;而不是把d…

Linux:查看进程。

Linux&#xff1a;查看进程。 windows linux TTY如果是&#xff1f;说明是不是终端(控制台)启动的&#xff0c;而是系统内部自己启动的。 TIME是启动Linux后&#xff0c;这个进程一共占用了cpu多少时间00…

《Spring Guides系列学习》guide46 - guide50

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gui…

《Python安全攻防:渗透测试实战指南》极致经典,学完即可包吃包住

前言 网络江湖&#xff0c;风起云涌&#xff0c;攻防博弈&#xff0c;从未间断&#xff0c;且愈演愈烈。从架构安全到被动纵深防御&#xff0c;再到主动防御、安全智能&#xff0c;直至进攻反制&#xff0c;皆直指安全的本质——攻防。未知攻&#xff0c;焉知防! 每一位网络安…

【Python】循环语句 ② ( while 嵌套循环 | 代码示例 - while 嵌套循环 )

文章目录 一、while 嵌套循环1、while 嵌套循环语法2、代码示例 - while 嵌套循环 一、while 嵌套循环 1、while 嵌套循环语法 while 嵌套循环 就是 在 外层循环 中 , 嵌套 内层循环 ; while 嵌套循环 语法格式 : while 外层循环条件:外层循环操作1外层循环操作2while 内存循…

VuePress + GitHub Actions 自动部署

文章目录 前言背景GitHub Actions简介基本概念引用 Actionworkflow 文件 自动部署创建 Action权限问题 小结参考文献 前言 我的第二本开源书籍《后台开发命令 365》上线啦。 为了方便阅读&#xff0c;使用 VuePress 将之前记录的后台常用 Linux 命令博文整理成一个系统的开源…

路径规划算法:基于阴阳对优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于阴阳对优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于阴阳对优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法…

Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!

前言 闲话 在我之前的文章 《Compose For Desktop 实践&#xff1a;使用 Compose-jb 做一个时间水印助手》 中&#xff0c;我埋了一个坑&#xff0c;关于在 Compose 中如何过滤 TextField 的输入内容。时隔好几个月了&#xff0c;今天这篇文章就是来填这个坑的。 为什么需要…

Doris

Aggregate 模型 是相同key的数据进行自动聚合的表模型。表中的列按照是否设置了 AggregationType&#xff0c;分为 Key&#xff08;维度列&#xff09;和 Value&#xff08;指标列&#xff09;&#xff0c;没有设置 AggregationType 的称为 Key&#xff0c;设置了 Aggregation…

散列表(哈希表)

目录 散列表 散列函数 散列表常用函数 1. 直接定址法 2. 除留余数法 2.1. exmple 3. 数字分析法 4. 平方取中法 5. 折叠法 处理冲突的方法 1. 开放定址法---线性探测 2. 二次探测法 3. 再Hash法 4. 拉链法(链地址法) 散列表&#xff08;Hash table&#xff0c;也…

Redis缓存击穿及解决问题

缓存击穿的意思是对于设置了过期时间的key,缓存在某个时间点过期的时候&#xff0c;恰好这时间点对这个 Key有大量的并发请求过来&#xff0c;这些请求发现缓存过期- -般都会从后端DB加载数据并回设到缓存&#xff0c;这个时候大并发的请求可能会瞬间把DB压垮。 解决方案有两种…

第五十四天学习记录:C语言进阶:动态内存管理Ⅱ

常见的动态内存错误 1、对NULL指针的解引用操作 int* p(int*)malloc(4); //p进行相关的判断 *p10;//malloc开辟空间失败&#xff0c;有可能对NULL指针解引用 free(p); pNULL;2、对动态开辟的内存的越界访问 int* p(int*)malloc(40);//10个int if(p!NULL) {int i0;//越界for(…

微服务项目租房网

文章目录 一、租房网项目的介绍1、使用的技术介绍2、使用的组件和开发工具的版本以及作用3、项目模块结构4、项目总体架构 二、环境搭建1、启动前端服务2、CentOS7各个组件的安装2.1 安装Docker2.2 安装JDK2.3 安装Redis(6390)2.4 安装FastDFS(8888)2.5 安装MongoDB(27017)2.6 …