在C语言中连接Oracle数据库,主要有以下几种方法:
1、使用OCI(Oracle Call Interface)
安装和配置OCI:在使用OCI之前,需要先安装Oracle客户端并配置环境变量,如ORACLE_HOME
和LD_LIBRARY_PATH
,在Linux系统中,可以在终端执行以下命令来设置环境变量:
export ORACLE_HOME=/path/to/oracle/client export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
编写OCI程序
初始化OCI环境:在进行数据库操作之前,需要初始化OCI环境。
OCIEnv *env; OCIError *err; if (OCIEnvCreate(&env, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL) != OCI_SUCCESS) { fprintf(stderr, "OCIEnvCreate failed "); return EXIT_FAILURE; } if (OCIHandleAlloc(env, (void *)&err, OCI_HTYPE_ERROR, 0, NULL) != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc for error handle failed "); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; }
连接数据库:使用OCILogon
函数进行数据库连接。
OCISvcCtx *svc; if (OCIHandleAlloc(env, (void *)&svc, OCI_HTYPE_SVCCTX, 0, NULL) != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc for service context failed "); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; } if (OCILogon(env, err, &svc, "username", strlen("username"), "password", strlen("password"), "dbname", strlen("dbname")) != OCI_SUCCESS) { fprintf(stderr, "OCILogon failed "); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; } printf("Connected to Oracle Database successfully! ");
执行SQL语句:首先创建语句句柄,然后使用OCIStmtPrepare
和OCIStmtExecute
函数执行SQL语句。
OCIStmt *stmt; if (OCIHandleAlloc(svc, (void *)&stmt, OCI_HTYPE_STMT, 0, NULL) != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc for statement handle failed "); OCILogoff(svc, err); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; } char *sql = "SELECT * FROM mytable"; if (OCIStmtPrepare(stmt, err, (const text *)sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT) != OCI_SUCCESS) { fprintf(stderr, "OCIStmtPrepare failed "); OCIHandleFree((void *)stmt, OCI_HTYPE_STMT); OCILogoff(svc, err); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; } if (OCIStmtExecute(svc, stmt, err, 1, 0, NULL, NULL, OCI_DEFAULT) != OCI_SUCCESS) { fprintf(stderr, "OCIStmtExecute failed "); OCIHandleFree((void *)stmt, OCI_HTYPE_STMT); OCILogoff(svc, err); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; }
处理结果集:定义变量来存储查询结果,并使用OCIDefineByPos
和OCIStmtFetch
函数处理结果集。
OCIDefine *defn; char result[100]; if (OCIHandleAlloc(env, (void *)&defn, OCI_HTYPE_DEFINE, 0, NULL) != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc for define handle failed "); OCIHandleFree((void *)stmt, OCI_HTYPE_STMT); OCILogoff(svc, err); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; } if (OCIDefineByPos(stmt, &defn, err, 1, (void *)result, sizeof(result), SQLT_STR, NULL, NULL, NULL, OCI_DEFAULT) != OCI_SUCCESS) { fprintf(stderr, "OCIDefineByPos failed "); OCIHandleFree((void *)defn, OCI_HTYPE_DEFINE); OCIHandleFree((void *)stmt, OCI_HTYPE_STMT); OCILogoff(svc, err); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIEnvFree(env, OCI_DEFAULT); return EXIT_FAILURE; } while (OCIStmtFetch(stmt, err, 1, OCI_FETCH_NEXT, OCI_DEFAULT) == OCI_SUCCESS) { printf("Result: %s ", result); }
清理资源:在程序结束时,需要清理分配的资源。
OCIHandleFree((void *)stmt, OCI_HTYPE_STMT); OCILogoff(svc, err); OCIHandleFree((void *)svc, OCI_HTYPE_SVCCTX); OCIHandleFree((void *)err, OCI_HTYPE_ERROR); OCIHandleFree((void *)env, OCI_HTYPE_ENV);
2、使用ODBC(Open Database Connectivity)
安装和配置ODBC:首先需要安装ODBC驱动程序,并配置数据源名称(DSN),可以使用命令行工具odbcinst
和配置文件odbc.ini
来进行配置,在Linux系统中,可以使用以下命令安装和配置ODBC:
sudo apt-get install unixodbc unixodbc-dev odbcinst -i -d -f /path/to/odbcinst.ini odbcinst -i -s -l -f /path/to/odbc.ini
编写ODBC程序
初始化ODBC环境:使用SQLAllocHandle
函数分配环境句柄,并设置ODBC版本。
SQLHENV env; SQLHDBC dbc; SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
连接数据库:使用SQLDriverConnect
函数连接到数据库。
SQLCHAR dsn[] = "DSN=mydsn;UID=username;PWD=password;"; SQLHDBC dbc; if (SQLDriverConnect(dbc, NULL, dsn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE) != SQL_SUCCESS) { fprintf(stderr, "SQLDriverConnect failed "); SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env); return EXIT_FAILURE; }
执行SQL语句:使用SQLExecDirect
或SQLPrepare
和SQLExecute
函数执行SQL语句。
SQLHSTMT stmt; SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); if (SQLExecDirect(stmt, (SQLCHAR *)"SELECT * FROM mytable", SQL_NTS) != SQL_SUCCESS) { fprintf(stderr, "SQLExecDirect failed "); SQLFreeHandle(SQL_HANDLE_STMT, stmt); SQLDisconnect(dbc); SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env); return EXIT_FAILURE; }
处理结果集:使用SQLBindCol
和SQLFetch
函数处理结果集。
SQLCHAR result[100]; if (SQLBindCol(stmt, 1, SQL_C_CHAR, result, sizeof(result), NULL) != SQL_SUCCESS) { fprintf(stderr, "SQLBindCol failed "); SQLFreeHandle(SQL_HANDLE_STMT, stmt); SQLDisconnect(dbc); SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env); return EXIT_FAILURE; } while (SQLFetch(stmt) == SQL_SUCCESS) { printf("Result: %s ", result); }
清理资源:在程序结束时,需要清理分配的资源。
SQLFreeHandle(SQL_HANDLE_STMT, stmt); SQLDisconnect(dbc); SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env);
3、**使用Pro*C预编译器
**安装和配置Pro*C**:首先需要安装Oracle客户端,并配置Pro*C环境,在Linux系统中,可以设置以下环境变量:
export ORACLE_HOME=/path/to/oracle/client export PATH=$ORACLE_HOME/bin:$PATH
**编写Pro*C程序**:在Pro*C程序中,可以直接嵌入SQL语句。
#include <stdio.h> #include <stdlib.h> #include <sqlca.h> EXEC SQL INCLUDE SQLCA; int main() { EXEC SQL BEGIN DECLARE SECTION; VARCHAR user[20], pass[20], tnsname[20]; char ename[20]; int empno; EXEC SQL END DECLARE SECTION; strcpy(user.arr, "umail"); user.len = (unsigned short)strlen((char *)user.arr); strcpy(pass.arr, "umail"); pass.len = (unsigned short)strlen((char *)pass.arr); strcpy(tnsname.arr, "umail"); tnsname.len = (unsigned short)strlen((char *)tnsname.arr); EXEC SQL CONNECT :user IDENTIFIED BY :pass USING :tnsname; EXEC SQL declare emp_cursor cursor for select id, ename from umail.tt1; EXEC SQL open emp_cursor; EXEC SQL WHENEVER NOT FOUND DO break; while (1) { EXEC SQL fetch emp_cursor into :empno, :ename; if (sqlca.sqlcode != 0) break; printf("the empno %d's name is %s/n", empno, ename); } printf("Yeah! We get %d records/n", empno); EXEC SQL close emp_cursor; EXEC SQL commit work release; return 0; }