C/C++

DCI 接口关于 LOB 字段示例

LOB 方法:

  • OCILobGetLength
   *用途:*返回大字段的长度,按字节计算。
   *格式:*  
    sword OCILobG etLength ( OCISvcCtx *svchp,
    OCIError*errhp,
    OCILobLocator *locp,
    ub4*lenp );
  • OCILobRead
   *用途:*读取某个大字段中指定长度的内容。
   *格式:*
     sword OCILobRe ad ( OCISvcCtx *svchp,
     OCIError*errhp,
     OCILobLocator *locp,
     ub4*amtp,
     ub4 offset,
     dvoid *bufp,
     ub4 bufl,
     dvoid*ctxp,
     OCICallbackLobRead (cbfp)
     ( dvoid *ctxp,
     CONST dvoid*bufp,
     ub4 len,
     ub1 piece
     )
     ub2 csid,
     ub1 csfrm );

未发现数据源名称并且未指定默认驱动程序

【问题描述】

[IM002][unixODBC][Driver Manager]Data source name not found, and no default driver specified.未发现数据源名称并且未指定默认驱动程序。[ISQL] ERROR: Could not SQLConnect。

【解决方法】

  • 第一种原因:odbc.ini 配置文件本身有问题,比如名称有空格。(odbc.ini 和 odbcinst.ini 中每行开头禁止留有空格)
  • 第二种原因:配置文件路径不对,请参考 Linux 平台配置 ODBC 连接达梦数据库
  • /etc 下的 odbc.ini 文件,要是 linux 格式的文档。
  • linux 上部署 ODBC 需要有 DM 数据库的驱动,要装一个 DM 数据库。
  • 参考技术链接:ODBC 接口

DSN 中,驱动程序和应用程序之间的体系结构不匹配

【问题描述】

"[Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配")/ODBC 数据源管理程序里没找到 DM 驱动。

【解决方法】

  • Win64 位系统有两个 ODBC 数据源管理器,分别为 64 位和 32 位。
    • 64 位 ODBC 数据源管理器路径是 C:\WINDOWS\system32\odbcad32.exe。
    • 32 位 ODBC 数据源管理器路径是 C:\WINDOWS\SysWOW64\odbcad32.exe。
  • Win64 位系统控制面板默认打开的 ODBC 数据源管理器是 64 位,在 Win64 系统安装 DM 版本后通过控制面板打开的 ODBC 数据源管理器发现找不到 ODBC 驱动,一般是由于安装的 DM 版本为 32 位,所以 64 位 ODBC 数据源管理器看不到,需要启动 32 位数据源管理器才可看到 ODBC 驱动。
    • 64 位应用程序只能调用 64 位 ODBC 驱动;
    • 32 位应用程序只能调用 32 位 ODBC 驱动;
  • 64 位应用程序调用 32 位 ODBC 驱动或 32 位应用程序调用 64 位 ODBC 驱动,都会提示以下错误:

Error: [Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配。

ODBC 连接 DM 数据库,报错:加密模块加载失败

【问题原因】

该问题是由于连接数据库时,调用 OpenSSL 加密动态库失败,针对该种报错,解决办法如下:

  • Windows 环境下

确认达梦安装目录下是否有 libeay32.dll,并且确认环境变量是否包含达梦安装目录,也可以将对应的动态库放置到 c:\windows\system32 目录下。

  • Linux 环境下

ODBC 接口调用依赖 libcrypt.so,程序执行时找不到 libcrypt.so 就会报错:加密动态库失败。
首先,检查 bin 目录下存在 libcrypt.so。
其次,确保 LD_LIBRARY_PATH 环境变量下包含达梦的安装目录 bin 目录。如:

export LD_LIBRARY_PATH=/home/dmdba/dm/dmdbms/bin

上述环境变量设置可以添加到对应用户的环境变量配置文件中。

【解决方法】

检查 bin 目录下存在 libcrypt.so,以及设置环境变量 LD_LIBRARY_PATH 指向 dmdbms/bin 目录。

communication error

【问题描述】

DM 数据库,MAX_SESSION=65000,在程序中没有设置 timeout 超时限制,C# 在插入数据库时会提示这个错误 communication error,循环插入前三万条可以,三万后就提示这个错误。

【解决方法】

检查 MAX_SESSION_STATEMENT 参数,检查每次插入是否新开了一个句柄,通过 select MAX(N_USED_STMT) from v$sessions;进行查看。

通过指定字符集的字符串获取字符集的 ID

【问题描述】

在进行对 DM 数据库编程时,使用 DM 的 DCI 用于兼容 Oracle 数据库的代码,在之前使用 Oracle 的 OCI 的编程的时候,可以通过 OCINlsCharSetNameToId 方法获取指定字符集的 id,現在在 DM 的 DCI 中未找到这个方法,在 DM 程序员手册也没有找到相关的 API 的说明。

【解决方法】

因为 DM 没有 NlsCharSetName 这个方法。DM 可以使用 SQL 语句 select UNICODE ();来获取指定字符集的 id。如果有兼容性需求,可通过对应销售或技术提需求。

ODBC 连接 DM 数据库报错

【问题描述】

ODBC 连接 DM 报错:can't open lib'/opt/dmdbms/bin/libdodbc.so':file not found 或者找不到.so 文件 error:could not SQLConnect。

【解决方法】

  • ldd /opt/dmdbms/bin/libdodbc.so 检查 libdodbc.so 依赖的文件是否有问题。
  • 依赖的 so 文件明明存在,但 ldd 仍提示找不到,一般是环境变量 LD_LIBRARY_PATH 设置问题。

解决方式:修改 /etc/profile.d 添加 LD_LIBRARY_PATH =$LD_LIBRARY_PATH: /opt/dmdbms/bin 设置,然后重新登录用户生效;或者 export 命令手动修改当前环境变量。

DmBulkCopy 提示[The faseloading dll not loading]

【问题描述】

DmBulkCopy 提示[The faseloading dll not loading],然后在 readme.txt 里面得知要引用 dmfldr_dll.dll 但是找到这个 dll。

【解决方法】

  • Linux 中把 DM 数据库的路径加到环境变量里面去。
  • Windows 的环境就把环境变量 path 加上 DM 数据库的路径。

Visual Studio 连接达梦数据库有没有专门的 DLL

没有专门的,Linux 是 libdodbc.so; Windows 是 DODBC.DLL。

语句句柄个数超上限或系统内存不足

【问题描述】

ODBC 访问达梦数据库,执行 SQL 语句报错:语句句柄个数超上限或系统内存不足。

【解决方法】

SQL 执行完成、断开连接前一定要释放语句句柄。“语句句柄个数超上限或系统内存不足”报错原因大部分是应用程序在断开连接前没有释放语句句柄导致。

可参考回滚记录版本太旧,无法获取用户记录

DM 是否能连接最新的 NetCore3.1 和 net5

DM8 可以。从达梦云适配中心下载试用下载最新版本数据库。

dpi_login 登陆数据库失败,获取错误信息描述为 70089 “加密模块加载失败”

这个是因为拷贝的动态库缺少第三方依赖导致的,建议您将 dmdbms/bin 目录也加到环境变量中即可。

应用报错 -30014

【问题描述】

现象表现是在调用测试程序时发生如下报错:

DM64 编译报错现象

【问题原因】

在 DPC 绑定参数时,由于送入的参数长度等信息为 INT 类型,DPC 绑定函数需要 INT64 类型参数,发生强制转换时,INT 的高四位填充偶发出现不是 0 的情况,导致送入参数值不正确,绑定失败,后执行报错。

【解决方法】

在进行编译时,需要添加 DM64 选项,否则会有风险,引发上述问题。详情请见文档《DM8-PROC》(位于数据库安装目录下的 doc)的 1.3.3 部分。

DM64 编译选项

清理环境之后重新进行编译,添加 DM64 选项,即可避免上述错误;

用 oracle occi 接口操作数据库,执行 getstring 方法时,开发工具崩溃

【问题描述】

使用 vs2019 或者 2013 开发工具,利用 oralce occi 接口操作数据库,执行 getstring 方法时,开发工具崩溃。

【解决方法】

需要根据 vs 开发工具版本申请对应的 occi 版本,请自行下载对应的 occi 驱动包。

proc*c 调用 fetch 异常

【问题描述】

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <memory.h>
#include <stdarg.h>
#include <sqlca.h>
#include <sqlda.h>
EXEC SQL INCLUDE SQLDA;

int db_connect(char *login)
{
 EXEC SQL BEGIN DECLARE SECTION;
   char  *logname = login;
 EXEC SQL END DECLARE SECTION;
 int  i = 0;

 printf("login: %s\n", logname);
 EXEC SQL CONNECT :logname;
 if (sqlca.sqlcode != 0) {
   printf("%s\n", sqlca.sqlerrm.sqlerrmc);
   return(-1);
 }
 return(0);
}

char col1[100][30], col2[100][30];

void fetchdata() {
 EXEC SQL FETCH DYN_SQL_C1 INTO :col1, :col2;
 printf("fetch %d\n", sqlca.sqlcode);
}

void main(int argc, char **argv) {
 if (argc != 2)
   exit(1);
 
 if (db_connect(argv[1]) < 0)
   exit(1);

 
 char psql[1024];
 
 strcpy(psql, "SELECT ROWNUM,to_char(sysdate,'yyyymmdd') optime FROM dual CONNECT BY ROWNUM<=30");
 
 EXEC SQL PREPARE DYN_SQL_01 FROM :psql;
 printf("prepare %d\n", sqlca.sqlcode);
 
 EXEC SQL DECLARE DYN_SQL_C1 CURSOR FOR DYN_SQL_01;
 printf("declare %d\n", sqlca.sqlcode);
 
 EXEC SQL OPEN DYN_SQL_C1;
 printf("open %d\n", sqlca.sqlcode);
 

 fetchdata();
 
 int ret_count = sqlca.sqlerrd[2];
 int i;
 
 for (i = 0; i < ret_count; i++) {
   printf("%d=%s,%s=\n", i, col1[i], col2[i]);
 }
 
 exit(0);
}

编译 pc 文件:

./dpc_new MODE=ORACLE file=a.pc
gcc -I/home/dmdba/dmdbms/include -g -L/home/dmdba/dmdbms/bin -ldmdpc -o a.out a.c

执行:

./a.out "SYSDBA/SYSDBA@192.168.104.72:5236"

此时报错:Segmentation fault

【原因分析】

应用程序编译缺少 DM64 宏,调用 64 位 dpc 动态库引发异常。

如果在 64 位机器上编译,需要加上 DM64 编译选项。由于 dpc_new 在编译时需要使用 DPItypes.h,而在 DPItypes.h 中定义了 slength 和 ulength 类型,如下所示:

#ifdef DM64
typedef sdint8 slength;
typedef udint8 ulength;
#define SLENGTH_MAX SDINT8_MAX
#define ULENGTH_MAX UDINT8_MAX
#else
typedef sdint4 slength;
typedef udint4 ulength;
#define SLENGTH_MAX SDINT4_MAX
#define ULENGTH_MAX UDINT4_MAX
#endif

因此,如果 64 位环境下编译应用时没加 DM64 宏,会导致 DPI 接口调用异常。

【解决方法】

gcc 编译时加上 DM64 参数:

gcc -I/home/dmdba/dmdbms/include -g -L/home/dmdba/dmdbms/bin -ldmdpc -o a.out a.c -D DM64

windows VS 下编译运行 dpi 程序

以下演示 windows 64 位系统,用 VS 创建 c++ 项目工程,添加源文件,编译运行 dpi 程序。

程序在编译的过程中需要用到 DM 的头文件 DPI.h、DPIext.h、DPItypes.h,在连接阶段需要用到 dmdpi.lib 这个库文件,在执行阶段需要用到动态库 dmdpi.dll 以及 dmcalc.dll、dmcomm.dll、dmcyt.dll、dmclientlex.dll、dmcvt.dll、dmelog.dll、dmmem.dll、dmmsg.dll、dmos.dll、dmutl.dll。这几个动态库在安装 DM 时,已经被放到安装目录下。

  • 添加头文件

选择属性——c/c++——附加包含目录,加入头文件路径。

加入头文件路径

头文件右键添加现有项,添加三个头文件。

添加三个头文件

  • 添加链接文件

选择属性——链接器——常规——附加库目录,加入 dmdpi.lib 的路径。

加入 dmdpi 路径

资源文件右键添加现有项,添加 dmdpi.lib。

添加现有项

  • 添加动态库文件

生成解决方案后,将动态库文件都复制到生成的项目目录下:

添加动态库文件

  • 添加编译参数 DM64

64 位平台需要添加编译参数 DM64,属性——c/c++——预处理器,添加 DM64

添加 DM64

sudo -u 指定其它用户后通过 odbc 连接提示找不到动态库文件

【问题描述】

使用 sudo -u 指定其它用户后通过 odbc 连接提示找不到动态库文件。报错如下:
[01000][unixODBC][Driver Manager]Can't open lib '/hom/dmdba/dmdbms/libdodbc.so' : file not found

【问题解决】

该问题是由于通过 sudo 切换用户执行命令时,无法通过 bashrc 等设置环境变量,当前 shell 的环境变量也无法继承导致,需要修改/etc/sudoers,使切换用户后能保持环境变量。修改方法如下:
编辑配置文件/etc/sudoers 并添加配置项:
Defaults env_keep += "LD_LIBRARY_PATH"

微信扫码
分享文档
扫一扫
联系客服