达梦8——接口DCI——基本概念;基本使用;
一、基本概念
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