ODBC应用程序测试过程学习笔记

概述

ODBC 是为客户应用程序访问关系数据库时提供的一个标准的接口,对于不同的数据库,ODBC 提供了统一的 API,使应用程序调用提供的 API 来访问任何提供了 ODBC 驱动程序的数据库.

  • 应用程序(Application,即对应下图的客户程序):应用程序本身不直接与数据库打交道,主要负责处理并调用ODBC函数,发送对数据库的SQL请求及获取结果.
  • 驱动程序管理器(Driver Manager,即对应下图的 ODBC 驱动管理程序):驱动程序管理器是一个带有输入程序的动态链接库(DLL),主要目的是加载驱动程序,处理ODBC调用的初始化调用,提供ODBC调用的参数有效性和序列有效性.
  • 驱动程序(Driver,即对应下图的 ODBC 驱动程序):驱动程序是一个完成ODBC函数调用并与数据库相互影响的DLL,这些驱动程序可以处理对于特定的数据的数据库访问请求.对于应用驱动程序管理器送来的命令,驱动程序再进行解释形成自己的数据库所能理解的命令.驱动程序将处理所有的数据库访问请求,对于应用程序来讲不需要关注所使用的是本地数据库还是网络数据库.
    在这里插入图片描述

相关文件及概述:

sql.h:  包含有基本的ODBC API的定义
sqlext.h:  包含有扩展的ODBC的定义
sqltypes.h:  包含有SQL的类型的定义
odbc32.lib:  库文件

ODBC应用程序编写

ODBC应用程序的编写步骤如下图:
在这里插入图片描述
在这里插入图片描述

建立 ODBC DSN

DSN(Data Source Name)是用于指定ODBC与相关的驱动程序相对应的一个入口,所有DSN的信息由系统进行管理,一般来讲当应用程序要使用ODBC访问数据库时,就需要指定一个DSN以便于连接到一个指定的ODBC驱动程序.
如下以连接oracle数据库为例,编写odbc应用测试例程
本地环境(CentOS 7.4 )配置ODBC连接oracle
1、安装oracle客户端及oracle ODBC驱动程序
下载oracle客户端包:https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html

rpm -ivh oracle-instantclient12.2-basic-12.2.0.1.0-1.x86_64.rpm 
rpm -ivh oracle-instantclient12.2-devel-12.2.0.1.0-1.x86_64.rpm 
rpm -ivh oracle-instantclient12.2-sqlplus-12.2.0.1.0-1.x86_64.rpm
rpm -ivh oracle-instantclient12.2-odbc-12.2.0.1.0-2.x86_64.rpm 

通过执行如下命令查看rpm安装后,将生成哪些文件及按照路径

rpm -qpl  oracle-instantclient12.2-odbc-12.2.0.1.0-2.x86_64.rpm          

配置环境变量

[myhost@local101:~/test/odbctest]$ sudo vim /etc/profile
 #根据实际安装路径配置
 export ORACLE_HOME=/usr/lib/oracle/12.2/client64/
 export TNS_ADMIN=/usr/lib/oracle/12.2/client64/network/admin
 export LD_LIBRARY_PATH=/usr/lib/oracle/12.2/client64/lib
 export ORACLE_SID=cdb1 (根据服务端的实际情况配置)
 export PATH=$ORACLE_HOME:$PATH
 export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin

source /etc/profile 使其生效

配置监听配置文件

mkdir -p /usr/lib/oracle/12.2/client64/network/admin
touch tnsnames.ora
sudo vim tnsnames.ora
# 增加如下内容
ORCL =
(DESCRIPTION =
  (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = 192.72.1.76)(PORT = 1521))
  )
  (CONNECT_DATA =
    (SERVICE_NAME = ORCL)
  )
)

2、安装 unixODBC 驱动程序管理器

  • 直接yum安装
yum install unixODBC unixODBC-devel
  • 源码编译安装
    请获取 unixODBC-2.3.1.tar.gz。 可以从 http://www.unixodbc.org 获取 unixODBC-2.3.1.tar.gz放到/usr/local下,然后运行下述命令:
    注意:如果自定义其他安装目录,需要配置环境变量,否则使用时可能会出现找不到库的问题
tar zxvf unixODBC-2.3.1.tar.gz
cd unixODBC-2.3.1 
./configure --prefix=/usr/local/unixODBC-2.3.1 --includedir=/usr/include 
--libdir=/usr/lib -bindir=/usr/bin --sysconfdir=/etc
make
make install

安装之后运行odbcinst -j

[myhost@local101:/usr/lib/oracle/12.2/client64/network/admin]$ odbcinst -j
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/uxdb/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

根据odbcinst -j 显示的路径,配置 odbcinst.iniodbc.ini 文件

[myhost@local101:~/test/odbctest]$ sudo vim /etc/odbcinst.ini

  1 # Example driver definitions
  2 
  3 # Driver from the postgresql-odbc package
  4 # Setup from the unixODBC package
  5 [PostgreSQL]
  6 Description = ODBC for PostgreSQL
  7 Driver      = /usr/lib/psqlodbcw.so
  8 Setup       = /usr/lib/libodbcpsqlS.so
  9 Driver64    = /usr/lib64/psqlodbcw.so
 10 Setup64     = /usr/lib64/libodbcpsqlS.so
 11 FileUsage   = 1
 12 
 13 
 14 # Driver from the mysql-connector-odbc package
 15 # Setup from the unixODBC package
 16 [MySQL]
 17 Description = ODBC for MySQL
 18 Driver      = /usr/lib/libmyodbc5.so
 19 Setup       = /usr/lib/libodbcmyS.so
 20 Driver64    = /usr/lib64/libmyodbc5.so
 21 Setup64     = /usr/lib64/libodbcmyS.so
 22 FileUsage   = 1
 23 
 # Driver from the oracle-connector-odbc package
 # Driver 根据Oracle ODBC驱动程序库的实际路径填写。
 25 [ORACLE]
 26 Description = ODBC for Oracle
 27 Driver      = /usr/lib/oracle/12.2/client64/lib/libsqora.so.12.1
 28 FileUsage   = 1
[myhost@local101:~/test/odbctest]$ sudo vim /etc/odbc.ini

## [oracle_test]为DSN名字,下面的driver对应odbcinst.ini文件中的驱动程序名,其他配置为连接相关信息,根据实际情况配置
  1 [oracle_test]
  2 
  3 driver = ORACLE
  4 
  5 server = 192.72.1.76
  6 
  7 port = 1521
  8 
  9 ServerName = ORCL
 10 
 11 UserID = ora_bbb
 12 
 13 password = bbb1234

连接测试

[myhost@local101:~]$ isql -v oracle_test
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> select * from t_a;
+-----------------------------------------+------+
| ID                                      | NAME |
+-----------------------------------------+------+
| 5                                       | jj   |
| 1                                       | a    |
| 2                                       | b    |
| 3                                       | c    |
| 4                                       | d    |
+-----------------------------------------+------+
SQLRowCount returns -1
5 rows fetched
SQL> 

ODBC应用程序编写

#include <stdio.h>
#include <sqlext.h>

int main() {
    SQLHENV env; // ODBC环境句柄
    SQLHDBC dbc; // ODBC连接句柄
    SQLRETURN ret;

    // Step 1: 初始化环境
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
    ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, SQL_IS_INTEGER);

    // Step 2: 分配连接句柄
    ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);

    // Step 3: 建立连接
    ret = SQLDriverConnect(dbc, NULL,
                           (SQLCHAR*)"DRIVER={Oracle};SERVER=<server>;DATABASE=<database>;UID=<username>;PWD=<password>;",
                           SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);

    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        printf("Connected to Oracle.\n");

        // Step 4: 执行SQL查询
        SQLHSTMT stmt; // SQL语句句柄
        ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);

        ret = SQLExecDirect(stmt, (SQLCHAR*)"SELECT * FROM my_table", SQL_NTS);

        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
            // 处理结果集
            // ...
            printf("SQL executed successfully.\n");
        } else {
            // 处理错误
            // ...
            printf("SQL execution failed.\n");
        }

        // Step 5: 释放语句句柄
        ret = SQLFreeHandle(SQL_HANDLE_STMT, stmt);
    } else {
        // 处理连接失败
        // ...
        printf("Failed to connect to Oracle.\n");
    }

    // Step 6: 断开连接
    ret = SQLDisconnect(dbc);

    // Step 7: 释放连接句柄
    ret = SQLFreeHandle(SQL_HANDLE_DBC, dbc);

    // Step 8: 释放环境句柄
    ret = SQLFreeHandle(SQL_HANDLE_ENV, env);

    return 0;
}

要编译以上的代码,首先需要确保已经安装了ODBC驱动和相关的开发库。接下来,可以使用gcc或其他支持C编译的工具进行编译。
例如,使用gcc命令编译该代码:

gcc -o odbc_demo odbc_demo.c -lodbc
gcc -o odbc_demo odbc_demo.c -L/odbc库的路径 -lodbc
#可通过下面的命令查找odbc库的路径
sudo find / -name "libodbc*"

其中,odbc_demo为输出的可执行文件名,odbc_demo.c为上述代码保存的文件名。-lodbc用于链接ODBC库。请注意,编译时可能需要配置包含路径和连接选项,具体取决于所使用的操作系统和ODBC驱动程序。

示例程序

vim odbctest.c
#include <stdio.h>

#include <sql.h>
#include <sqlext.h>


static void
test_SQLConnect()
{
	SQLRETURN ret;
    SQLHENV env;
    SQLHDBC conn;
    HSTMT hstmt = SQL_NULL_HSTMT;
    SQLSMALLINT sdwNative;
	SQLINTEGER swMsgLen;
	char buffer[256];
	char message[1000];

	SQLCHAR *dsn = (SQLCHAR *) "oracle_test";
    //CHAR* queryStr="create table tt_lqq(id int);";

	SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);

	SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);

	SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);

	printf("Connecting with SQLConnect...\n");

	ret = SQLConnect(conn, dsn, SQL_NTS, NULL, 0, NULL, 0);
	if (SQL_SUCCEEDED(ret)) {
		printf("connected success!\n");
	} else {
		printf("SQLConnect failed.\n");
		return;
	}

    ret = SQLSetConnectAttr(conn,
						   SQL_ATTR_AUTOCOMMIT,
						   (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
						   SQL_IS_UINTEGER);
	if (SQL_SUCCEEDED(ret)) {
		printf("set autommit off success!\n");
	} else {
		printf("set autommit failed.\n");
		return;
	}

    ret = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);

    ret = SQLExecDirect(hstmt, (SQLCHAR *)"create table tt_lqq(id int)", SQL_NTS);
    if (SQL_SUCCEEDED(ret)) {
		printf("create table success!\n");
	}
    else {
		printf("create table failed.\n");
		return;
	}

    ret = SQLExecDirect(hstmt, (SQLCHAR *) "INSERT INTO tt_lqq VALUES (10000)", SQL_NTS);
	if (SQL_SUCCEEDED(ret)) {
		printf("insert table success!\n");
	}
    else {
		printf("insert table failed.\n");
		return;
	}

    SQLEndTran(SQL_HANDLE_DBC, conn, SQL_COMMIT);
    if (SQL_SUCCEEDED(ret)) {
		printf("SQLEndTran success!\n");
	}
    else {
		printf("SQLEndTran failed.\n");
		return;
	}

    ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    if (SQL_SUCCEEDED(ret)) {
		printf("SQLFreeHandle success!\n");
	}
    else {
		printf("SQLFreeHandle failed.\n");
		return;
	}

    ret = SQLDisconnect(conn);
	if (SQL_SUCCEEDED(ret)) {
		printf("SQLDisconnect success!\n");
	}
    else {
        printf("SQLDisconnect failed.\n");
        SQLError(env, conn, hstmt, buffer, &swMsgLen,
		message, 256, &sdwNative);
		printf("%s\n%s\n", buffer, message);
		return;
	}

	ret = SQLFreeHandle(SQL_HANDLE_DBC, conn);
	if (!SQL_SUCCEEDED(ret))
	{
		printf("SQLFreeHandle failed\n");
		return;
	}
	conn = NULL;

	ret = SQLFreeHandle(SQL_HANDLE_ENV, env);
	if (!SQL_SUCCEEDED(ret))
	{
		printf("SQLFreeHandle failed\n");
		return;
	}
	env = NULL;
}


int main(int argc, char **argv)
{
	test_SQLConnect();
	return 0;
}

通过以下命令进行编译,第一条命令用于将UnixODBC驱动库安装在系统路径下,第二条命令可用于源码编译安装时,将UnixODBC安装在自定义路径下,可找到对应的odbc动态库路径,通过-L指定库的路径,-I指定所需头文件的路径等等

gcc -o odbctest2 odbctest2.c -lodbc
gcc -o odbctest2 odbctest2.c -L/usr/lib64/ -lodbc

执行可执行程序

[myhost@local101:~/test/odbctest]$ ./odbctest2 
Connecting with SQLConnect...
connected success!
set autommit off success!
create table success!
insert table success!
SQLEndTran success!
SQLFreeHandle success!
SQLDisconnect success!

OCI应用测试程序的编写

oci应用程序的编写步骤和odbc流程一致,只是调用的接口不同,提供如下样例

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


#include "oci.h" //引用OCI接口的头文件,因此编译时需要指定该头文件的路径
 
/*user name and password*/
static text* username=(text *)"ora_bbb";
static text* password=(text *)"bbb1234";
static text* oracle=(text *)"192.72.1.76/orcl";
 
/* Define SQL statements to be used in program. */
static text* SQL=(text *)"insert into tt_lqq(id1, id2) values (:1, :2)";
 
/*handle define*/
static OCIEnv             *p_env;                                        //OCI environment handle
static OCIError         *p_err;                                        //OCI error handle
static OCISvcCtx        *p_svc;                                        //OCI service context handel
static OCIServer        *p_ser;                                        //OCI server handle
static OCISession        *p_usr;                                        //OCI user session handle
static OCIStmt            *p_sql;                                        //OCI statement handle
static OCIDefine        *p_dfn = (OCIDefine *)NULL;            //OCI define handle
static OCIBind            *p_bnd = (OCIBind *)NULL;                //OCI bind handle
 
/*create OCI environment*/
int create_env()
{
    int swResult;            //Return value
    if(swResult = OCIEnvCreate(&p_env,OCI_DEFAULT,NULL,NULL,NULL,NULL,0,NULL))
        {
            printf("environment create error!\n\n");
            return -1;
        }
    else
        {
            printf("environment create success!\n\n");
            return 0;
        }
}
 
/*init handle*/
int init_handle()
{
    int swResult;
    if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_ser,OCI_HTYPE_SERVER,0,NULL))    //服务器句柄
        {
            printf("init server handle error!\n\n");
            return -1;
        }
    else
        {
            printf("init server handle success!\n\n");
        }
 
    if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_err,OCI_HTYPE_ERROR,0,NULL))    //错误句柄
        {
            printf("init error handle error!\n\n");
            return -1;
        }
    else
        {
            printf("init error handle success!\n\n");
        }
    if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_usr,OCI_HTYPE_SESSION,0,NULL))    //事务句柄
        {
            printf("init session handle error!\n\n");
            return -1;
        }
    else
        {
            printf("init session handle success!\n\n");
        }
    if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_svc,OCI_HTYPE_SVCCTX,0,NULL))    //上下文句柄
        {
            printf("init service context handle error!\n\n");
            return -1;
        }
    else
        {
            printf("init service context handel success!\n\n");
        }
    if(swResult = OCIHandleAlloc(p_env,(dvoid *)&p_sql,OCI_HTYPE_STMT,0,NULL))        //SQL语句句柄
        {
            printf("init statement handle error!\n\n");
            return -1;
        }
    else
        {
            printf("init statement handle success!\n\n");
        }
    return 0;
}
 
/*connect server*/
int conn_server()
{
    int swResult;
    if(swResult = OCILogon(p_env,p_err,&p_svc,(text *)username,strlen(username),(text *)password,strlen(password),(text *)oracle,strlen(oracle)))
        {
            printf("connect error!\n\n");
            return -1;
        }
    else
        printf("connect success!\n\n");
    return 0;
}
 
/*SQL statements*/
int oci_exec()
{
    int swResult;
	sb4 errcodep;
	ub4 recordno = 1;
	OraText bufp[1024];
	sword retcode = 0;

    //准备SQL语句
    if(swResult = OCIStmtPrepare(p_sql,p_err,SQL,strlen(SQL),OCI_NTV_SYNTAX,OCI_DEFAULT))
        {
            printf("prepare SQL statements error!\n\n");
        }
    else
        {
            printf("prepare SQL statements success!\n\n");
        }
 
    //设置绑定变量
    int getId1 ;
	int getId2;
    //char getName[10];
 
    OCIBind     *p_bndp1 = NULL;
    OCIBind     *p_bndp2 = NULL;
 
    printf("输入ID1,ID2:\n");
    scanf("%d %d",&getId1,&getId2);
 
    if(swResult = OCIBindByPos(p_sql,&p_bndp1,p_err,1,(dvoid *)&getId1,(sb4)sizeof(getId1),SQLT_INT,NULL,NULL,NULL,0,NULL,OCI_DEFAULT))
        {
            printf("Bind p1 error!\n\n");
            return -1;
        }
    else
        {
            printf("bind success!\n\n");
        }

	 if(swResult = OCIBindByPos(p_sql,&p_bndp2,p_err,2,(dvoid *)&getId2,(sb4)sizeof(getId2),SQLT_INT,NULL,NULL,NULL,0,NULL,OCI_DEFAULT))
        {
            printf("Bind p1 error!\n\n");
            return -1;
        }
    else
        {
            printf("bind success!\n\n");
        }

	/*
    if(swResult = OCIBindByPos(p_sql,&p_bndp2,p_err,2,&getName,(sb4)sizeof(getName),SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT))
        {
            printf("Bind p2 error!\n\n");
            return -1;
        }
    else
        {
            printf("bind success!\n\n");
        }*/
 
 
    //执行SQL statements
    if(swResult = OCIStmtExecute(p_svc,p_sql,p_err,1,0,NULL,NULL,OCI_DEFAULT))
        {
            //printf("execute SQL statement error!\n\n");
			if (OCIErrorGet(p_err, recordno++, NULL, &errcodep, (OraText *)bufp, sizeof(bufp), OCI_HTYPE_ERROR) == OCI_SUCCESS)
				printf("error msg:%s\n", bufp);
            return -1;
        }
    else
        {
            printf("execute SQL statement success!\n\n");
        }
    return 0;
}
 
 
/*quit server*/
void quit_server()
{
    OCILogoff(p_svc,p_err);
    printf("Quit success!\n");
}
 
/*free handle*/
void free_handle()
{
    OCIHandleFree(p_ser,OCI_HTYPE_SERVER);            //释放服务器句柄
    OCIHandleFree(p_err,OCI_HTYPE_ERROR);            //释放错误句柄
    OCIHandleFree(p_usr,OCI_HTYPE_SESSION);        //释放事务句柄
    OCIHandleFree(p_svc,OCI_HTYPE_SVCCTX);            //释放上下文句柄
    OCIHandleFree(p_sql,OCI_HTYPE_STMT);            //释放SQL语句句柄
}
 
int main()
{
    if(create_env() == -1)                //创建环境
        return -1;
    if(init_handle() == -1)                //初始化句柄
        return -1;
    if(conn_server() == -1)                //连接数据库
        return -1;
    if(oci_exec() == -1)
        return -1;
	/*
    quit_server();                            //退出数据库
    free_handle();                            //释放句柄 */
    return 0;
}

样例可以看到调用OCI相关接口需要引用oci.h这个头文件,那么 这个头文件在哪?
该头文件是在安装完oracle客户端之后,对应oracle-instantclient12.2-devel-12.2.0.1.0-1.x86_64.rpm软件包,可以通过如下命令查看其安装之后的路径

[myhost@local101:~/oracle]$ rpm -qpl oracle-instantclient12.2-devel-12.2.0.1.0-1.x86_64.rpm
/usr/include/oracle/12.2/client64/ldap.h
/usr/include/oracle/12.2/client64/nzerror.h
/usr/include/oracle/12.2/client64/nzt.h
/usr/include/oracle/12.2/client64/occi.h
/usr/include/oracle/12.2/client64/occiAQ.h
/usr/include/oracle/12.2/client64/occiCommon.h
/usr/include/oracle/12.2/client64/occiControl.h
/usr/include/oracle/12.2/client64/occiData.h
/usr/include/oracle/12.2/client64/occiObjects.h
/usr/include/oracle/12.2/client64/oci.h
/usr/include/oracle/12.2/client64/oci1.h
/usr/include/oracle/12.2/client64/oci8dp.h
/usr/include/oracle/12.2/client64/ociap.h
/usr/include/oracle/12.2/client64/ociapr.h
/usr/include/oracle/12.2/client64/ocidef.h
/usr/include/oracle/12.2/client64/ocidem.h
/usr/include/oracle/12.2/client64/ocidfn.h
/usr/include/oracle/12.2/client64/ociextp.h
/usr/include/oracle/12.2/client64/ocikpr.h
/usr/include/oracle/12.2/client64/ocixmldb.h
/usr/include/oracle/12.2/client64/ocixstream.h
/usr/include/oracle/12.2/client64/odci.h
/usr/include/oracle/12.2/client64/oratypes.h
/usr/include/oracle/12.2/client64/ori.h
/usr/include/oracle/12.2/client64/orid.h
/usr/include/oracle/12.2/client64/orl.h
/usr/include/oracle/12.2/client64/oro.h
/usr/include/oracle/12.2/client64/ort.h
/usr/include/oracle/12.2/client64/xa.h
/usr/lib/oracle/12.2/client64/lib/libclntsh.so
/usr/lib/oracle/12.2/client64/lib/libclntshcore.so
/usr/lib/oracle/12.2/client64/lib/libocci.so
/usr/lib/oracle/12.2/client64/lib/ottclasses.zip
/usr/share/oracle/12.2/client64/admin/oraaccess.xsd
/usr/share/oracle/12.2/client64/demo/cdemo81.c
/usr/share/oracle/12.2/client64/demo/demo.mk
/usr/share/oracle/12.2/client64/demo/occidemo.sql
/usr/share/oracle/12.2/client64/demo/occidemod.sql
/usr/share/oracle/12.2/client64/demo/occidml.cpp
/usr/share/oracle/12.2/client64/demo/occiobj.cpp
/usr/share/oracle/12.2/client64/demo/occiobj.typ
/usr/share/oracle/12.2/client64/demo/oraaccess.xml
/usr/share/oracle/12.2/client64/demo/ott
/usr/share/oracle/12.2/client64/demo/setuporamysql.sh
[myhost@local101:~/oracle]$ 

接下来编译上述样例:

gcc -o ocitest ocitest.c -I/usr/include/oracle/12.2/client64 -L${ORACLE_HOME}/lib -lclntsh

执行可执行程序

[myhost@local101:~test/ocitest]$ ./ocitest 
environment create success!

init server handle success!

init error handle success!

init session handle success!

init service context handel success!

init statement handle success!

connect success!

prepare SQL statements success!

输入ID1,ID2:
5 6
bind success!

bind success!

execute SQL statement success!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值