一、基本概念
OCI(Oracle Call Interface)是 ORACLE 公司開發的一個接口,C語言、C++通過這個接口,可以訪問 Oracle 數據庫;
DM DCI 是參照 OCI 的接口標准,結合自身的特點,為C或C++開發人員提供訪問達夢數據庫的一款接口產品。
二、基本使用
1、下載Visual Studio等C可用IDE;
2、新建空的C項目,新建C文件,把以下源碼復制到C文件中;
/************************************************************************/ /* DCI編程實例 */ /************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include "DCI.h" /* 聲明句柄 */ OCIEnv* envhp; /* 環境句柄 */ OCISvcCtx* svchp; /* 服務環境句柄 */ OCIServer* srvhp; /* 服務器句柄 */ OCISession* authp; /* 會話句柄 */ OCIStmt* stmthp; /* 語句句柄 */ OCIDescribe* dschp; /* 描述句柄 */ OCIError* errhp; /* 錯誤句柄 */ OCIDefine* defhp[3]; /* 定義句柄 */ OCIBind* bidhp[4]; /* 綁定句柄 */ sb2 ind[3]; /* 指示符變量 */ /* 綁定select結果集的參數 */ text szpersonid[11]; /* 存儲personid列 */ text szsex[2]; /* 存儲sex列 */ text szname[51]; /* 存儲name列 */ text szemail[51]; /* 存儲mail列 */ text szphone[26]; /* 存儲phone列 */ char sql[256]; /* 存儲執行的sql語句*/ int main(int argc, char* argv[]) { char strServerName[50]; char strUserName[50]; char strPassword[50]; int ret; text errbuf[100]; /* 設置服務器,用戶名和密碼 */ strcpy(strServerName, "localhost"); strcpy(strUserName, "SYSDBA"); strcpy(strPassword, "SYSDBA"); /* 初始化OCI應用環境*/ OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL); /* 初始化環境句柄 */ OCIEnvInit(&envhp, OCI_DEFAULT, 0, 0); /* 分配句柄 */ OCIHandleAlloc(envhp, (dvoid**)&svchp, OCI_HTYPE_SVCCTX, 0, 0); /*服務器環境句柄*/ OCIHandleAlloc(envhp, (dvoid**)&srvhp, OCI_HTYPE_SERVER, 0, 0); /* 服務器句柄*/ OCIHandleAlloc(envhp, (dvoid**)&authp, OCI_HTYPE_SESSION, 0, 0); /* 會話句柄 */ OCIHandleAlloc(envhp, (dvoid**)&errhp, OCI_HTYPE_ERROR, 0, 0); /* 錯誤句柄 */ OCIHandleAlloc(envhp, (dvoid**)&dschp, OCI_HTYPE_DESCRIBE, 0, 0); /*描述符句柄*/ /* 連接服務器 */ OCIServerAttach(srvhp, errhp, (text*)strServerName,(sb4)strlen(strServerName), OCI_DEFAULT); /* 設置用戶名和密碼 */ OCIAttrSet(authp, OCI_HTYPE_SESSION, (text*)strUserName,(ub4)strlen(strUserName), OCI_ATTR_USERNAME, errhp); OCIAttrSet(authp, OCI_HTYPE_SESSION, (text*)strPassword,(ub4)strlen(strPassword), OCI_ATTR_PASSWORD, errhp); /* 設置服務器環境句柄屬性 */ OCIAttrSet((dvoid*)svchp, (ub4)OCI_HTYPE_SVCCTX, (dvoid*)srvhp, (ub4)0, OCI_ATTR_SERVER, errhp); OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, (dvoid*)authp, 0, OCI_ATTR_SESSION, errhp); /* 創建並開始一個用戶會話 */ OCISessionBegin(svchp, errhp, authp, OCI_CRED_RDBMS, OCI_DEFAULT); OCIHandleAlloc(envhp, (dvoid**)&stmthp, OCI_HTYPE_STMT, 0, 0); /* 語句句柄 */ ///************************************************************************/ ///* 查詢person表 */ ///************************************************************************/ strcpy(sql, "select personid, name, phone from sysdba.person"); /* 准備SQL語句 */ OCIStmtPrepare(stmthp, errhp, (text*)sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT); /* 綁定輸出列 */ OCIDefineByPos(stmthp, &defhp[0], errhp, 1, (ub1*)szpersonid, sizeof(szpersonid), SQLT_STR, &ind[0], 0, 0, OCI_DEFAULT); OCIDefineByPos(stmthp, &defhp[1], errhp, 2, (ub1*)szname, sizeof(szname), SQLT_STR, &ind[1], 0, 0, OCI_DEFAULT); OCIDefineByPos(stmthp, &defhp[2], errhp, 3, (ub1*)szphone, sizeof(szphone), SQLT_STR, &ind[2], 0, 0, OCI_DEFAULT); /* 執行SQL語句 */ ret = OCIStmtExecute(svchp, stmthp, errhp, (ub4)0, 0, NULL, NULL, OCI_DEFAULT); if (ret != 0) { OCIErrorGet(errhp, 1, NULL, &ret, (OraText*)errbuf, sizeof(errbuf), OCI_HTYPE_ERROR); printf("%s\n", errbuf); } printf("%-10s%-10s%-10s\n", "PERSONID", "NAME", "PHONE"); while ((OCIStmtFetch(stmthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) != OCI_NO_DATA) { printf("%-10s", szpersonid); printf("%-10s", szname); printf("%-10s\n", szphone); } /************************************************************************/ /* 向person表插入一條數據 */ /************************************************************************/ memset(sql, 0, sizeof(sql)); strcpy(sql, "insert into sysdba.person(sex, name, email, phone) values(:sex,:name,:email,:phone)"); /* 准備SQL語句 */ OCIStmtPrepare(stmthp, errhp, (text*)sql, strlen(sql), OCI_NTV_SYNTAX, OCI_DEFAULT); /* 設置輸入參數 */ memset(szsex, 0, sizeof(szsex)); strcpy(szsex, "FM"); memset(szname, 0, sizeof(szname)); strcpy(szname, "張三"); memset(szemail, 0, sizeof(szemail)); strcpy(szemail, "z@g.com"); memset(szphone, 0, sizeof(szphone)); strcpy(szphone, "027-00"); /* 綁定輸入列 */ OCIBindByName(stmthp, &bidhp[0], errhp, ":sex", 4, szsex, strlen((char*)szsex), SQLT_AFC, NULL, NULL, NULL, 0, NULL, 0); OCIBindByName(stmthp, &bidhp[1], errhp, ":name", 5, szname, strlen((char*)szname), SQLT_AFC, NULL, NULL, NULL, 0, NULL, 0); OCIBindByName(stmthp, &bidhp[2], errhp, ":email", 6, szemail, strlen((char*)szemail), SQLT_AFC, NULL, NULL, NULL, 0, NULL, 0); OCIBindByName(stmthp, &bidhp[3], errhp, ":phone", 6, szphone, strlen((char*)szphone), SQLT_AFC, NULL, NULL, NULL, 0, NULL, 0); /* 執行SQL語句 */ ret = OCIStmtExecute(svchp, stmthp, errhp, (ub4)1, (ub4)0, (CONST OCISnapshot*) 0, (OCISnapshot*)0, (ub4)OCI_DEFAULT); if (ret != 0) { OCIErrorGet(errhp, 1, NULL, &ret, (OraText*)errbuf, sizeof(errbuf), OCI_HTYPE_ERROR); printf("%s\n", errbuf); } /* 提交到數據庫 */ OCITransCommit(svchp, errhp, OCI_DEFAULT); //結束會話 OCISessionEnd(svchp, errhp, authp, (ub4)0); //斷開與數據庫的連接 OCIServerDetach(srvhp, errhp, OCI_DEFAULT); //釋放OCI句柄 OCIHandleFree((dvoid*)dschp, OCI_HTYPE_DESCRIBE); OCIHandleFree((dvoid*)stmthp, OCI_HTYPE_STMT); OCIHandleFree((dvoid*)errhp, OCI_HTYPE_ERROR); OCIHandleFree((dvoid*)authp, OCI_HTYPE_SESSION); OCIHandleFree((dvoid*)svchp, OCI_HTYPE_SVCCTX); OCIHandleFree((dvoid*)srvhp, OCI_HTYPE_SERVER); return 0; }
3、添加依賴
由於在編譯的過程中需要用到 DM 的頭文件 dci.h,
在連接階段需要用到 dmoci.lib 這個庫文件,
在執行階段需要用到動態庫 dmoci.dll、dmcalc.dll、dmelog.dll、dmmen.dll、dmos.dll、dmutl.dll、
在連接階段需要用到 dmoci.lib 這個庫文件,
在執行階段需要用到動態庫 dmoci.dll、dmcalc.dll、dmelog.dll、dmmen.dll、dmos.dll、dmutl.dll、
dmclientlex.dll、dmfldr_dll.dll、dmbcast.dll、dmdta.dll、dmcfg.dll、dmstrt.dll、dmcpr.dll、dmcyt.dll、dmcvt.dll、dmmout.dll、dmdpi.dll、dmcomm.dll。
所以,我們需要添加這些依賴項;
具體步驟:
- 右擊項目,打開屬性,
- C/C++ -> 常規 -> 附加包含目錄 -> c:\dmdbms\include
- 鏈接器 -> 附加庫目錄 -> c:\dmdbms\include
- 鏈接器 -> 附加依賴項 -> dmoci.lib
當我們添加好依賴后,main.c文件里的“以來未找到”就會消失了;
4、建表
由於main.c文件里需要查詢和插入sysdba模式下的person表,所以打開DM管理工具,去sysdba模式下新建一個person表;
這里要注意,到底是去新建一個person表,還是PERSON表,如果dm初始化實例時選擇的是大小寫不敏感,則無所謂;
但如果dm選擇的大小寫敏感,那就有所謂了,否則會找不到表;
首先大小寫敏感下的person表和PERSON表不一樣,
其次是dm的sql解釋器自動把所有字母轉換為大寫字母,如果大小寫敏感的話,我們小寫的表名和列名就找不到了;
如果不想要dm解釋器自動轉換我們輸入的sql,就要在對象名上加雙引號,這樣dm解釋器就回去找小寫的表明和列名了;;
5、執行
點擊‘調式’, 點擊‘開始執行(不調試)’
注意:如果報strcpy不全的錯誤,可以右擊項目屬性->C/C++->預處理器->預處理器定義中添加:_CRT_SECURE_NO_WARNINGS 參考:https://blog.csdn.net/qq_33757398/article/details/81204372