`
ppgunjack
  • 浏览: 81532 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

使用oci封装库ocilib访问oracle

阅读更多
讲下背景,目前项目当中使用occi的一个封装库编写dao,但这个方案并不是特别理想。
对于Oracle对待occi的态度一直不太理解,oci的api非常复杂,而对简单很多的occi Oracle支持力度却非常有限。
在Oracle安装版本当中,只提供很少的几个occi编译库。
而且occi库对编译器,编译器版本,数据库版本,crt版本,操作平台版本都有诸多限制。
尽管window上occi也提供了支持vs的链接库,但在window上并不是任何版本的vs都能支持,稍老的05都不支持10G带的的occi库。
在linux上甚至有低版本gcc支持,然后版本高点的gcc反而不支持的情况。
以前写代码本来期望window上mingw测试,unix上部署,结果发觉mingw根本没有能用的occi链接库,而在unix上都得很折腾然后才能让occi正常跑起来。
要注意的是occi支持的编译器、OS平台、各自版本都有限制,如果通过occi访问Oracle一定要确认未来的production运行和编译环境是否明确在支持列表。

采取oci访问Oracle则好很多,c库在mingw,vs都可以透明使用,而且对各个主流OS和编译器也都能很好支持,这样很容易就做到一次编写,多处运行,window下用mingw写出的代码很容易移到unix或linux的gcc甚至acc下。
但oci的缺点也很明显:api太复杂,一个简单的功能也要写大量代码。
于是出现了一些封装oci但是是以类jdbc或者occi风格的wrapper库,比如oraLib,ocilib,ocl。这里介绍一下ocilib:
ocilib封装的oci.lib,以c lib的形式提供给用户,这样使得基于它编写的代码如果今后转到其他平台和编译器上几乎没有需要改动的地方。
并且ocilib支持的数据库特性非常多,换句话说它对多数的oci api都提供了封装,并且以简洁的接口暴露给开发者。
ocilib是lgpl的license,这意味你只要不静态链接ocilib或者封装它,可以免费用到你的商业产品中(封装的话需要开源封装部分的代码)。

下面是一个简单的建立数据库连接的代码:
#include "ocilibDemo.h"

void err_handler(OCI_Error *err)
{
    printf(
                "code  : ORA-%05i\n"
                "msg   : %s\n"
                "sql   : %s\n",
                OCI_ErrorGetOCICode(err), 
                OCI_ErrorGetString(err),
                OCI_GetSql(OCI_ErrorGetStatement(err))
           );
}

void conn()
{
    OCI_Connection *cn; 

    if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
        return;

    cn = OCI_ConnectionCreate(tnsName, user, password, OCI_SESSION_DEFAULT);

    if (cn != NULL) {
        printf(OCI_GetVersionServer(cn)); 

        printf("Server major    version : %i\n", OCI_GetServerMajorVersion(cn)); 
        printf("Server minor    version : %i\n", OCI_GetServerMinorVersion(cn)); 
        printf("Server revision version : %i\n", OCI_GetServerRevisionVersion(cn)); 

        printf("Connection      version : %i\n", OCI_GetVersionConnection(cn)); 

        /* ... application code here ... */ 

        OCI_ConnectionFree(cn); 
    }

    OCI_Cleanup(); 

    return; 
}

其中err_handler是作为异常处理函数,会在数据库error发生时被调用。
注意ocilib代码在编译时要设置宏/DOCI_API=__stdcall和/DOCI_CHARSET_XXX,XXX是具体字符集类型有三种:
-  OCI_CHARSET_ANSI     : all strings are in ANSI
-  OCI_CHARSET_UNICODE  : all strings are Unicode (versions of Oracle> = 9i) 
-  OCI_CHARSET_MIXED    : SQL statements + metadata are in ANSI, user data and resultset data in Unicode
客户端和服务器端最好都统一设置ANSI或者UNICODE,避免麻烦。

下面是些简单的dml代码:
void  createTable(){
    OCI_Statement  *st = NULL;
    OCI_Connection *cn;

    if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
        return;

    cn = OCI_ConnectionCreate(tnsName, user, password, OCI_SESSION_DEFAULT);

    if (cn!=NULL) {
        st = OCI_StatementCreate(cn);
        char sql[]=MT("create table test_table ")
                   MT("( ")
                   MT("val_int  number, ")
                   MT("val_flt  float, ")
                   MT("val_str  varchar2(30), ")
                   MT("val_date date")
                   MT(")");
        cout<<"Create table:\n"<<sql<<endl;
        OCI_ExecuteStmt(st, sql);
        OCI_ConnectionFree(cn); 
    }

    OCI_Cleanup();
}

void dropTable(){
    OCI_Statement  *st = NULL;
    OCI_Connection *cn;

    if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
        return;

    cn = OCI_ConnectionCreate(tnsName, user, password, OCI_SESSION_DEFAULT);

    if (cn!=NULL) {
        st = OCI_StatementCreate(cn);
        char sql[]=MT("drop table test_table");
        cout<<"Drop table:\n"<<sql<<endl;
        OCI_ExecuteStmt(st, sql);
        OCI_ConnectionFree(cn); 
    }

    OCI_Cleanup();
}

void insertBind(){
    OCI_Date *date;

    int i;
    double flt;

    OCI_Statement  *st = NULL;
    OCI_Connection *cn;

    if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
        return;

    cn = OCI_ConnectionCreate(tnsName, user, password, OCI_SESSION_DEFAULT);
    if (cn!=NULL) {
        st = OCI_StatementCreate(cn);
        char sql[]=MT("insert into test_table ")
                   MT("( ")
                   MT("   val_int,  val_flt, val_str, val_date")
                   MT( ") " )
                   MT( "values ")
                   MT( "( ")
                   MT( "   :val_int, :val_flt, :val_str, :val_date")
                   MT(") ");
        cout<<"Intsert table:\n"<<sql<<endl;
        OCI_Prepare(st, sql);
        i   = 1;
        flt = 3.14;
        string s="sfsdfsdfsfsdfsdfsd";
        date = OCI_DateCreate(cn);
        OCI_DateSysDate(date);

        OCI_BindInt(st, MT(":val_int"),  &i);
        OCI_BindDouble(st, MT(":val_flt"), &flt);
        OCI_BindString(st, MT(":val_str"), const_cast<char *>(s.c_str()), 30);
        OCI_BindDate(st, MT(":val_date"), date);
        OCI_Execute(st);
        OCI_DateFree(date);
        OCI_Commit(cn);

        OCI_ConnectionFree(cn); 
    }

    OCI_Cleanup();
}

void insertArray(){
    OCI_Connection *cn;
    OCI_Statement  *st;
    OCI_Error      *err;
    int count=20000000;

    int batchSize=5000;
    int tab_int[batchSize];
    double tab_flt[batchSize];
    char tab_str[batchSize][31];
    OCI_Date* tab_date[batchSize];

    int i;

    if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
        return;

    cn = OCI_ConnectionCreate(tnsName, user, password, OCI_SESSION_DEFAULT);
    st = OCI_StatementCreate(cn);

    OCI_Prepare(st, "insert into test_table values(:i, :f, :s, :t)");
    OCI_BindArraySetSize(st, batchSize);
    OCI_BindArrayOfInts(st, ":i", tab_int, 0);
    OCI_BindArrayOfDoubles(st, ":f", tab_flt, 0);
    OCI_BindArrayOfStrings(st, ":s", (char*) tab_str, 30, 0);
    OCI_BindArrayOfDates(st,":t",tab_date,0);


    for (i=0;i<batchSize;i++) {
        tab_int[i] = i+1;
        tab_flt[i]=3.14;
        sprintf(tab_str[i],"Name %d",i+1);

        tab_date[i] = OCI_DateCreate(cn);
        OCI_DateSysDate(tab_date[i]);
    }

    int round=count/batchSize;

    clock_t start=clock();
    cout<<start<<endl;
    for (int j=0;j<round;j++) {
        if (!OCI_Execute(st)) {
            printf("Number of DML array errors : %d\n", OCI_GetBatchErrorCount(st));       

            err = OCI_GetBatchError(st);

            while (err) {
                printf("Error at row %d : %s\n", OCI_ErrorGetRow(err), OCI_ErrorGetString(err));       

                err = OCI_GetBatchError(st);
            }
        }
        OCI_Commit(cn);
//      printf("row processed : %d\n", OCI_GetAffectedRows(st));
    }

    clock_t stop=clock();
    cout<<stop<<endl;
    int costTime=stop-start;
    double numberPerSec=(count/costTime)*1000;
    cout<<"Insert records "<<count<<" cost time "<<costTime<<" ms"<<endl;
    cout<<"Insert records "<<numberPerSec<<"records/s "<<endl;
    for (i=0;i<batchSize;i++) {
        OCI_DateFree(tab_date[i]);
    }
    OCI_Commit(cn);
    OCI_ConnectionFree(cn);
    OCI_Cleanup();

    return;
}

ocilib的代码可以跑在装有Oracle client或instant client的任何机器上,通过tns访问数据库,如果是instant client注意设置tns和home路径。
更多的例子可以查看ocilib自带的demo和文档,ocilib的demo非常完备,提供了它支持的所有特性的例子
分享到:
评论
1 楼 hyuuuu 2013-02-05  
insertArray()

关于批量绑定OCI_LONG,OCI_RAW 和OCI_Blob,有这方面的例子

相关推荐

    避开10大常见坑:DeepSeekAPI集成中的错误处理与调试指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    前端分析-2023071100789

    前端分析-2023071100789

    基于kinect的3D人体建模C++完整代码.cpp

    基于kinect的3D人体建模C++完整代码.cpp

    搞机工具箱10.1.0.7z

    搞机工具箱10.1.0.7z

    GRU+informer时间序列预测(Python完整源码和数据)

    GRU+informer时间序列预测(Python完整源码和数据),python代码,pytorch架构,适合各种时间序列直接预测。 适合小白,注释清楚,都能看懂。功能如下: 代码基于数据集划分为训练集测试集。 1.多变量输入,单变量输出/可改多输出 2.多时间步预测,单时间步预测 3.评价指标:R方 RMSE MAE MAPE,对比图 4.数据从excel/csv文件中读取,直接替换即可。 5.结果保存到文本中,可以后续处理。 代码带数据,注释清晰,直接一键运行即可,适合新手小白。

    性价比革命:DeepSeekAPI成本仅为GPT-4的3%的技术揭秘.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水模拟dem-sph-fem耦合 ,基于ANSYS LSDyna; 滑坡入水模拟; DEM-SPH-FEM 耦合,基于DEM-SPH-FEM耦合的ANSYS LSDyna滑坡入水模拟

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    复件 复件 建设工程可行性研究合同[示范文本].doc

    复件 复件 建设工程可行性研究合同[示范文本].doc

    13考试真题最近的t64.txt

    13考试真题最近的t64.txt

    Microsoft Visual C++ 2005 SP1 Redistributable PackageX86

    好用我已经解决报错问题

    嵌入式开发入门:用C语言点亮LED灯的全栈开发指南.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    自动立体库设计方案.pptx

    自动立体库设计方案.pptx

    手把手教你用C语言实现贪吃蛇游戏:从算法设计到图形渲染.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    性能对决:DeepSeek-V3与ChatGPTAPI在数学推理场景的基准测试.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    从零到一:手把手教你用Python调用DeepSeekAPI的完整指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    为什么你的switch总出bug?90%新手不知道的break语句隐藏规则.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    用deepseek变现实操流程

    用deepseek变现实操流程,小白必看。

    10个必知的DeepSeekAPI调用技巧:从鉴权到限流全解析.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

Global site tag (gtag.js) - Google Analytics