使用IBPP在C++中操作FireBird/Interbase数据库(部分修正)

转载自http://www.oschina.net/docs/article/11527

FireBird是一种小巧的关系型数据库,它有多种版本,包括服务器版(象MySQL),单机版(象Access)以及嵌入式(象SQLite)。而且不管是服务器版还是嵌入式版它都完整支持视图、触发器、存储过程等SQL高级特性。
问题是它提供的C API“不太友好”,不容易掌握(特别是我),所以我一直只会在C++Builder里编程使用FireBird(因为FireBird源于 Borland的InterBase,VCL库自带了InterBase的组件),直到有一天我发现了IBPP...

IBPP是一个 FireBird/Interbase数据库API的C++包装,使用起来也比较简单,只要把IBPP源码目录里的 "core/all_in_one.cpp"加入工程,在代码中包含头文件"ibpp.h",最后根据操作系统预定义一个IBPP_WINDOWS或 IBPP_UNIX的宏即可。
另外,当然还要安装FireBird客户端,如果只是学习,我们可以下载嵌入式版本。IBPP首先要找到FireBird的动态库,在Windows下, IBPP在下面的路径中查找:

  • 在程序目录下查找fbembed.dll
  • 在程序目录下查找fbclient.dll
  • 依据DefaultInstance注册表键值查找fbclient.dll
  • 在系统定义位置查找fbclient.dll
  • 在系统定义位置查找gds32.dll


FireBird主页:http://www.ibphoenix.com
IBPP主页:http://www.ibpp.org
关于FireBird的中文教程我推荐姚启红编著的《Borland InterBase7.0 应用开发指南》(网上一找一大堆)。

例一,基本应用

(开始编译总是有告警,且运行时弹出错误对话框。使用编译选项/GR代替/Gm解决)

  1. #include <iostream>
  2. #include "../../Source/ibpp/core/ibpp.h"
  3. using namespace std;
  4. const char* g_szDBName = "X:/db/xxxx.fdb";
  5. const char* g_szServerName = "";
  6. const char* g_szUserName = "XXXXXX";
  7. const char* g_szPassword = "123456";
  8. void main()
    {
    try{
       IBPP::Database db = IBPP::DatabaseFactory(g_szServerName,
        g_szDBName,
        g_szUserName,
        g_szPassword);

         //连接数据库
       db->Connect();

       IBPP::Transaction tr = IBPP::TransactionFactory(db);
       tr->Start();
       try{
        IBPP::Statement st = IBPP::StatementFactory(db,tr);
        st->Execute("SELECT FIRST 10 NAME,ADDRESS FROM CUSTOM_INFO");
        //显示SELECT得到的数据
        while(st->Fetch())
        {
         string name, address;
         st->Get("NAME",name);
         st->Get("ADDRESS",address);
         cout << "NAME:" << name << " ADDRESS:" << address << endl;
        }
        tr->Commit();
       }catch(IBPP::SQLException& e){
        cerr << e.what() << endl;
        tr->Rollback();
       }
       db->Disconnect();
    }catch(IBPP::SQLException& e){
       cout << "ERR: " << e.ErrorMessage();
    }
    }

要让程序正确执行,就得保证程序能找到FireBird的动态链接库。对于嵌入式版本来说,下载后把压缩包中的fbembed.dll, firebird.conf,firebird.msg,ib_util.dll以及intl文件夹解压到你的程序目录中就可以运行了。对于服务器版,只要安装客户端并把fbclient.dll放到程序目录里就行(当然权限也要有啦)。
上例中使用IBPP的步骤是:

  1. 用工厂函数IBPP::DatabaseFactory生成IBPP::Database实例,然后调用它的Connect成员变量连接数据库。
  2. 如果要建立数据库的话,使用Database::Create(int dialect)。其中dialect一般取值为3,它的含义如下:
SQL Dialect含义
1兼容InterBase 5.5及更早版本。
21和3的过渡版本。
3InterBase 6.0及以后版本,可以使用分隔符,精确数字和时间格式。
  1. 使用工厂函数IBPP::TransactionFactory生成IBPP::Transaction实例,然后用它的Start开始事务,最后用Commit来提交事务或Rollback撤销事务。
  2. 使用工厂函数IBPP::StatementFactory生成IBPP::Statement实例,然后用它的Execute来执行SQL命令。
  3. 值 得注意的是,IBPP中的Database,Transaction,Statement等由工厂函数返回的数据都是智能指针类型,它们能够在退出有效域 时自动执行一些保证完整性的操作。(比如我们使用tr->Start后即便不调用tr->Commit,在超出tr变量作用域后系统 也会自动调用Commit的)
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <assert.h>
  4. #include <ibpp.h>
  5. using namespace std;
  6. //数据库名,根据你的情况更改。
  7. const char* g_szDBName = "d://test.fdb";
  8. //服务器名,针对服务器版本。对于嵌入式,它应该是""
  9. const char* g_szServerName = "";
  10. //这里的用户名和密码是FireBird默认值,对于服务器版,用你自己的密码
  11. //对于嵌入式,就是这个(FireBird嵌入式版没有加密功能)。
  12. const char*     g_szUserName = "SYSDBA";
  13. const char* g_szPassword = "masterkey";
  14. int main
  15. {
  16.      IBPP::Database db;
  17.      db = IBPP::DatabaseFactory(g_szServerName,
  18.          g_szDBName,
  19.          g_szUserName,
  20.          g_szPassword);
  21.     //连接数据库
  22.      db->Connect;
  23.      IBPP::Transaction tr = IBPP::TransactionFactory(db);
  24.      tr->Start;
  25.     try{
  26.          IBPP::Statement st = IBPP::StatementFactory(db,tr);
  27.         //建立数据表
  28.          st->ExecuteImmediate(
  29.             "CREATE TABLE BlobTable("
  30.             "     ID INTEGER NOT NULL,"
  31.             "     RES BLOB)"
  32.              );
  33.         //生成器
  34.          st->ExecuteImmediate(
  35.             "CREATE GENERATOR BlobTable_ID_Gen"
  36.              );
  37.         //触发器
  38.          st->ExecuteImmediate(
  39.             "CREATE TRIGGER BlobTable_BI_ID FOR BlobTable "
  40.             "ACTIVE BEFORE INSERT POSITION 0 "
  41.             "AS "
  42.             "BEGIN "
  43.             "     IF(NEW.ID IS NULL) THEN "
  44.             "         NEW.ID = GEN_ID(BlobTable_ID_Gen, 1); "
  45.             "END"
  46.          );
  47.          tr->CommitRetain;
  48.        
  49.          st->Prepare("INSERT INTO BlobTable(RES) VALUES(?)");
  50.          assert(1 == st->Parameters);
  51.         //插入Blob,一块100字节的内存
  52.          {
  53.              IBPP::Blob res = IBPP::BlobFactory(db,tr);
  54.              res->Create;
  55.             char buf[100];
  56.             for(int i=0; i<100; i++) buf[i]=i;
  57.              res->Write(buf,sizeof(buf));
  58.              res->Close;
  59.              st->Set(1,res); //第一个问号
  60.              st->Execute;
  61.          }
  62.         //插入Blob,一串字符串
  63.          {
  64.              st->Set(1,string("HAHAHAHAHAHA..."));
  65.              st->Execute;
  66.          }
  67.          tr->Commit;
  68.      }
  69.     catch(IBPP::SQLException &e){
  70.          cerr << e.what << endl;
  71.          tr->Rollback;
  72.      }
  73.      tr->Start;
  74.     try{
  75.          IBPP::Statement st = IBPP::StatementFactory(db,tr);
  76.          st->Execute("SELECT * FROM BlobTable");
  77.         //显示SELECT得到的数据
  78.         while(st->Fetch)
  79.          {
  80.             int id;
  81.              IBPP::Blob res = IBPP::BlobFactory(db,tr);
  82.              st->Get(1,id);
  83.              st->Get(2,res);
  84.            
  85.             //显示Blob内容
  86.              res->Open;
  87.             int size;
  88.              res->Info(&size,NULL,NULL);
  89.              cout << id << " size is " << size << endl;
  90.             char c;
  91.             while(res->Read(&c,1))
  92.              {
  93.                  cout << (int)c << ' ';
  94.              }
  95.              cout << endl;
  96.          }
  97.          tr->Commit;
  98.      }
  99.     catch(IBPP::SQLException &e){
  100.          cerr << e.what << endl;
  101.          tr->Rollback;
  102.      }
  103. }


本例连接例一建立的数据库,然后新建一个名为BlobTable的表,里面只有ID和RES字段,而且还为ID字段建立了一个生成器和触发器,这样就可以 让FireBird自动为ID赋值了,具体内容可以看FireBird教程。与例一不同的是这里使用了IBPP::Statement的 ExecuteImmediate方法,它立即执行其中的SQL语句,而Execute则有一个先准备、再执行的过程,对于只执行一次的SQL, 可以使用ExecuteImmediate,如果执行次数较多,则建议使用Execute。
RES字段是一个Blob型字段,从本例可以看出给Blob字段赋值的方法是:

  1. 用IBPP::Statement的Prepare方法准备SQL插入语句,其中的Blob字段使用问号?代替。
  2. 用工厂函数IBPP::BlobFactory生成一个IBPP::Blob实例,然后分别调用它的Create,Write和Close输入数据,最后用IBPP::Statement的Set方法写入。
  3. 所有数据准备就绪后,执行IBPP::Statement的Execute方法。

如果只想往Blob中存放文本数据,也可以直接用IBPP::Statement的Set方法写入std::string类型。
从Blob字段取值的方法正好相反:

  1. 用IBPP::Statement的Execute方法或ExecuteImmediate方法执行SELECT语句。
  2. 使用IBPP::Statement的Fetch方法提取出当前行的数据。
  3. 使用IBPP::Statement的Get方法取出指定列的数据,如果是Blob类型,则使用IBPP::Blob实例作为输入。
  4. 最后分别调用IBPP::Blob的Open,Read和Close方法取出数据(IBPP::Blob也是一个智能指针类型,所以上例中没有显式地使用Close关闭)。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值