C语言ODBC连接DM8之动态获取字段示例(SQLDescribeCol)

如何配置odbc环境请进行文章跳转 配置ODBC环境连接达梦数据库

一、数据库导入SQL语句

CREATE TABLE "PRODUCT_CATEGORY"
(
"PRODUCT_CATEGORYID" INT IDENTITY(1, 1) NOT NULL,
"NAME" VARCHAR(50) NOT NULL,
"ORD_AMT" NUMBER(19,0),
CLUSTER PRIMARY KEY("PRODUCT_CATEGORYID")) STORAGE(ON "MAIN", CLUSTERBTR) ;

insert into "PRODUCT_CATEGORY" ("NAME","ORD_AMT") values ('11', 111);
insert into "PRODUCT_CATEGORY" ("NAME","ORD_AMT") values ('22', 222);

commit;

select PRODUCT_CATEGORYID,NAME,round(11100000*100/10000*(1+233/10000000000*30))*1000 ORD_AMT from PRODUCT_CATEGORY;



select PRODUCT_CATEGORYID,NAME,round(1110*100/10000*(1+233/10000000000*30))*1000 ORD_AMT from PRODUCT_CATEGORY;

二、C语言动态获取字段的例子

#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#include <unistd.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 hstmt;/* 语句句柄 */
SQLRETURN sret; /* 返回代码 */
SQLSMALLINT col, cols;



int main(void)
{
	/* 申请一个环境句柄 */
	SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
	/* 设置环境句柄的 ODBC 版本 */
	SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,
		SQL_IS_INTEGER);
	/* 申请一个连接句柄 */
	SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
       	int     out_c1 = 0;
	SQLCHAR out_c2[20] = { 0 };
	SQLLEN  out_c1_ind = 0;
	SQLLEN  out_c2_ind = 0;

//	sret = SQLConnect(hdbc, (SQLCHAR *)"192.168.145.167:5236", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS);
	sret = SQLConnect(hdbc, "DM8", SQL_NTS, "SYSDBA", SQL_NTS, "SYSDBA", SQL_NTS);
	
	if (RC_NOTSUCCESSFUL(sret)) {
		/* 连接数据源失败! */
		printf("odbc: fail to connect to server!,result %d\n",sret);


              // 连接失败,获取错误信息
      SQLCHAR state[6];
      SQLINTEGER error_code;
      SQLCHAR message[SQL_MAX_MESSAGE_LENGTH];
      SQLSMALLINT message_length;
      SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, state, &error_code, message, SQL_MAX_MESSAGE_LENGTH, &message_length);
      printf("Failed to connect to database: %s\n", message);



		SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
		SQLFreeHandle(SQL_HANDLE_ENV, henv);
		exit(0);
	}
	printf("odbc: connect to server success!\n");

    int i;
    for (i=1; i<=2; ++i){	

	SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
     SQLExecDirect(hstmt, (SQLCHAR *) "select PRODUCT_CATEGORYID,NAME,round(11100000*100/10000*(1+233/10000000000*30))*1000 ORD_AMT from PRODUCT_CATEGORY", SQL_NTS);    
    // SQLExecDirect(hstmt, (SQLCHAR *) "select PRODUCT_CATEGORYID,NAME,round(1110*100/10000*(1+233/10000000000*30))*1000 ORD_AMT from PRODUCT_CATEGORY", SQL_NTS);   
     SQLCHAR col_name[256];
        SQLSMALLINT col_name_len, data_type, scale, nullable;
        SQLULEN col_size;
        sret = SQLDescribeCol(hstmt, 3, col_name, 256, &col_name_len, &data_type, &col_size, &scale, &nullable);

	   // Print column information
    printf("Column Name: %s\n", col_name);
    printf("Data Type: %d\n", data_type);
    printf("Column Size: %ld\n", col_size);
    printf("Decimal Digits: %d\n", scale);
    printf("Nullable: %d\n", nullable);

//	SQLCHAR col_name[256];
//        SQLINTEGER  col_name_len;

  //      sret  = SQLGetDescField(hstmt, col, SQL_DESC_NAME, col_name, sizeof(col_name), &col_name_len);
     

	SQLBindCol(hstmt, 1, SQL_C_SLONG, &out_c1, sizeof(out_c1), &out_c1_ind);
	SQLBindCol(hstmt, 2, SQL_C_CHAR, &out_c2, sizeof(out_c2), &out_c2_ind);

	printf("odbc: select from table...\n");
	while (SQLFetch(hstmt) != SQL_NO_DATA)
	{


                


		printf("c1 = %d, c2 = %s ,\n", out_c1, out_c2);
	}
	printf("odbc: select success\n");
	sleep(2);
   }		
	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);


	/* 断开与数据源之间的连接 */
	SQLDisconnect(hdbc);
	/* 释放连接句柄 */
	SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
	/* 释放环境句柄 */
	SQLFreeHandle(SQL_HANDLE_ENV, henv);

	return 0;
}

三、编译C程序并运行

[root@localhost bin]# cat /usr/local/unixODBC-arm/etc/odbcinst.ini
[DM8 ODBC DRIVER]
Description=DM ODBC driver for DM8
Driver=/opt/dmdbms_1_2_198_test/bin/libdodbc.so
[root@localhost bin]# cat /usr/local/unixODBC-arm/etc/odbc
odbc.ini      odbcinst.ini  
[root@localhost bin]# cat /usr/local/unixODBC-arm/etc/odbc.ini 
[DM8]
DRIVER=DM8 ODBC DRIVER
SERVER=127.0.0.1
UID=SYSDBA
PWD=SYSDBA
TCP_PORT=5236

##查看配置的odbc是否可用
[root@localhost bin]# /usr/local/unixODBC-2.3.0/exe/isql DM8 -v

##如果可行的话

##设置变量库
[root@localhost bin]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/unixODBC-arm/lib/
[root@localhost bin]# export LD_LIBRARY_PATH=/opt/dmdbms_1_2_198_test/bin:$LD_LIBRARY_PATH
##编译C文件 
[root@localhost bin]# gcc -o odbc_conn odbc_conn_1.c  -I /opt/dmdbms_1_2_198_test/include -I /usr/local/unixODBC-arm/include -L /opt/dmdbms_1_2_198_test/bin -L /opt/dmdbms_1_2_198_test/drivers/odbc -DDM64 -lpthread -ldodbc
## 执行
[root@localhost bin]# ./odbc_conn

四、报错原因

1. Failed to connect to database: 无效的配置值(Invalid config value)

image.png
解决方案:

  1. 配置LD_LIBRARY_PATH环境 添加 ODBC lib目录。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/unixODBC-arm/lib/

  1. 代码中SQLConnect的host不能写ip,要写配置的dsn

当使用ODBC连接数据库时,SQLConnect函数可能会返回错误代码SQL_INVALID_DSN或SQL_INVALID_PARAMETER。其中SQL_INVALID_DSN表示数据源名称无效,而SQL_INVALID_PARAMETER表示指定的用户名或密码无效。具体来说,当SQLConnect函数返回错误代码SQL_INVALID_PARAMETER并报告“Invalid config value”错误时,这可能是以下问题之一导致的:

  1. 无效的用户名或密码:请确保指定的用户名和密码正确,并且与数据库中的凭据匹配。如果您使用的是Windows身份验证,则需要使用Windows域用户账户和密码。
  2. 数据库连接字符串的格式不正确:请检查您使用的连接字符串是否正确。例如,如果您使用的是DSN,则请确保DSN的名称正确,并且在DSN的属性中指定了正确的数据库名称、用户名和密码。如果您使用的是直接的连接字符串,则请确保格式正确并包含正确的数据库名称、用户名和密码等信息。
  3. 防火墙或网络问题:如果数据库服务器受到防火墙或网络限制,则可能无法建立连接。请检查您的网络设置和防火墙设置,确保允许与数据库服务器的通信。此外,您还需要确保数据库服务器正在运行,并且可以通过网络访问。
  4. 缺少必需的ODBC驱动程序:如果您正在使用ODBC驱动程序连接数据库,则需要确保安装了正确的ODBC驱动程序。如果缺少所需的驱动程序,则连接尝试可能会失败,并显示“Invalid config value”错误。

以上是一些可能导致ODBC连接失败并报告“Invalid config value

2. Data source name not found and no default driver specified

odbcinst -j
image.png
解决方案:

  1. 环境多人使用 odbc比较混乱,其实就是找不到配置文件中的信息
  2. 调整/usr/bin目录下isql引用即可,随后测试
cd /usr/local/unixODBC-2.3.0/exe
cp -r isql /usr/bin/
isql DM7 SYSDBA SYSDBA

资料包

链接:https://pan.baidu.com/s/1moVsFmCW4Wc3SvOxgFtqbw?pwd=zhpv
提取码:zhpv

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值