Berkeley DB——Cursor

Berkeley DB——Cursor
Introduction
Berkeley DB 的游标( Dbc )和关系数据库的游标是类似的——一种可以迭代数据库中的记录的装置。对于重复记录,使用游标来访问他们会更加方便(使用 Db bulk get 来得到多条记录是性能最高的做法)。另外,通过游标可以一条条地操作(修改和删除)记录。
在使用游标之前,必须先使用 Db::cursor 方法打开游标:
int Db::cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags);
游标打开后可以通过游标 search write 记录。使用完毕后,必须关闭之:
int Dbc::close(void);
例子:
#include <db_cxx.h>
...
Dbc *cursorp;
Db my_database(NULL, 0);
// Database open omitted for clarity
// Get a cursor
my_database.cursor(NULL, &cursorp, 0);
// Database and cursor open omitted for clarity
// Do something…
if (cursorp != NULL)
    cursorp->close();
Getting Records from DB Using Cursor
打开数据库,并打开此数据库的游标后,就可以使用该游标来 search DB 来遍历符合条件的记录了。
Dbc::get 方法的 flag 参数可以取多个值,常用的有:
Flag
Description
DB_CURRENT
返回游标当前所指的 key/data
DB_FIRST
游标指向第一条记录,并返回该 key/data
DB_GET_BOTH
只有 key/data 都匹配才返回该 key/data
DB_GET_RECNO
返回行号。数据库必须是 B 树的,且其 flag DB_RECNUM
DB_LAST
DB_FIRST 对应
DB_NEXT
游标指向下条记录,并返回下个 key/data
DB_PREV
DB_NEXT 对应
DB_MULTIPLE
返回该 key 的所有记录。数据库是允许重复记录的。
例子:
#include <db_cxx.h>
...
Db my_database(NULL, 0);
Dbc *cursorp;
try {
    // Database open omitted for clarity
    // Get a cursor
    my_database.cursor(NULL, &cursorp, 0);
    Dbt key, data;
    int ret;
    // Iterate over the database, retrieving each record in turn.
    while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) {
        // Do interesting things with the Dbts here.
    }
    if (ret != DB_NOTFOUND) {
        // ret should be DB_NOTFOUND upon exiting the loop.
        // Dbc::get() will by default throw an exception if any
        // significant errors occur, so by default this if block
        // can never be reached.
    }
} catch(DbException &e) {
        my_database.err(e.get_errno(), "Error!");
} catch(std::exception &e) {
        my_database.errx("Error! %s", e.what());
}
// Cursors must be closed
if (cursorp != NULL)
    cursorp->close();
my_database.close(0);
Operating Records Using Cursor
Dbc 对象提供了 put del get 方法,通过这些方法我们可以写入、删除和获取记录。
例子:
#include "stdafx.h"
#include <iostream>
#include <db_cxx.h>
#include <string.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
       Db db(NULL,0);
      
       u_int32_t oFlags = DB_CREATE; // Open flags;
       try
       {
              db.open(NULL,                // Transaction pointer
                     "my_db.db",          // Database file name
            NULL,                // Optional logical database name
            DB_BTREE,            // Database access method
            oFlags,              // Open flags
            0);                  // File mode (using defaults)
              db.truncate(NULL,0,0);
              float money = 122.45;
              char *description = "Grocery bill.";
              Dbt key(&money, sizeof(float));
              Dbt data(description, strlen(description)+1);
              int ret = db.put(NULL, &key, &data, DB_NOOVERWRITE);
              cout<<"put data--"<<description<<endl;
              ret = db.get(NULL, &key, &data, DB_GET_BOTH);
              cout<<"get key--"<<*((float*)key.get_data())<<endl;
              cout<<"get data--"<<(char *)data.get_data()<<endl;
              money = 111;
              description = "James--------------------";
             data.set_data(description);
              data.set_size(strlen(description)+1);
              db.put(NULL,&key,&data,DB_NOOVERWRITE);
              ret = db.get(NULL, &key, &data, DB_GET_BOTH);
              cout<<"get key--"<<*((float*)key.get_data())<<endl;
              cout<<"get data--"<<(char *)data.get_data()<<endl;
              money = 191;
              description = "Mike";
              data.set_data(description);
              data.set_size(strlen(description)+1);
              db.put(NULL,&key,&data,DB_NOOVERWRITE);
              ret = db.get(NULL, &key, &data, DB_GET_BOTH);
              cout<<"get key--"<<*((float*)key.get_data())<<endl;
              cout<<"get data--"<<(char *)data.get_data()<<endl;
              Dbc* cursor;
              db.cursor(NULL,&cursor,0);
              cout<<"open cursor"<<endl;
             
              while((ret = cursor->get(&key,&data,DB_PREV)) != DB_NOTFOUND)
              {
                     cout<<"get key--"<<*((float*)key.get_data())<<endl;
                     cout<<"get data--"<<(char *)data.get_data()<<endl;
              }
              if (cursor != NULL)
              {
                     cursor->close();
              }
              money = 191;
              description = "Mike";
              data.set_data(description);
              data.set_size(strlen(description)+1);
              db.cursor(NULL,&cursor,0);
              cout<<"delete 191..."<<endl;
              while((ret = cursor->get(&key,&data,DB_SET)) == 0 )
              {
                     cursor->del(0);
              }
              if (cursor != NULL)
              {
                     cursor->close();
              }
              cout<<"after delete 191..."<<endl;
              db.cursor(NULL,&cursor,0);
              while((ret = cursor->get(&key,&data,DB_PREV)) != DB_NOTFOUND)
              {
                     cout<<"get key--"<<*((float*)key.get_data())<<endl;
                     cout<<"get data--"<<(char *)data.get_data()<<endl;
              }
              if (cursor != NULL)
              {
                     cursor->close();
              }
       }
       catch(DbException &e)
       {
              cerr<<"DBException:"<<e.what();
       }
       catch(std::exception &e)
       {
              cerr<<"DBException:"<<e.what();
       }
       system("pause");
       return 0;
}
Joining Cursors
Berkeley DB 支持两个数据库之间的“对等”连接,即当数据库 A cursor 和数据库 B cursor 进行 join 时,返回数据库 A key 和数据库 B data 相等的记录。也就是说,实际的数据是存在 A 中的 data 里面,而通过数据库 B key 来获得 A data 。比如:
数据库 A
A-Key
A-Data
apple
Convenience Store
blueberry
Farmer's Market
peach
Shopway
pear
Farmer's Market
raspberry
Shopway
strawberry
Farmer's Market
数据库 B
B-Key
B-Data:
Blue
blueberry
red
apple
red
raspberry
red
strawberry
yellow
peach
yellow
pear
则根据 B 的一条记录( key Blue ), join 后应该返回的是数据库 A key blueberry 的记录,即 data Farmer's Market
例子:
#include <db_cxx.h>
#include <string.h>
...
// Exception handling omitted
int ret;
Db automotiveDB(NULL, 0);
Db automotiveColorDB(NULL, 0);
Db automotiveMakeDB(NULL, 0);
Db automotiveTypeDB(NULL, 0);
// Database and secondary database opens omitted for brevity.
// Assume a primary database:
//   automotiveDB
// Assume 3 secondary databases:
//   automotiveColorDB -- secondary database based on automobile color
//   automotiveMakeDB -- secondary database based on the manufacturer
//   automotiveTypeDB -- secondary database based on automobile type
// Position the cursors
Dbc *color_curs;
automotiveColorDB.cursor(NULL, &color_curs, 0);
char *the_color = "red";
Dbt key(the_color, strlen(the_color) + 1);
Dbt data;
if ((ret = color_curs->get(&key, &data, DB_SET)) != 0) {
    // Error handling goes here
}
Dbc *make_curs;
automotiveMakeDB.cursor(NULL, &make_curs, 0);
char *the_make = "Toyota";
key.set_data(the_make);
key.set_size(strlen(the_make) + 1);
if ((ret = make_curs->get(&key, &data, DB_SET)) != 0) {
    // Error handling goes here
}
Dbc *type_curs;
automotiveTypeDB.cursor(NULL, &type_curs, 0);
char *the_type = "minivan";
key.set_data(the_type);
key.set_size(strlen(the_type) + 1);
if ((ret = type_curs->get(&key, &data, DB_SET)) != 0) {
    // Error handling goes here
}
// Set up the cursor array
Dbc *carray[4];
carray[0] = color_curs;
carray[1] = make_curs;
carray[2] = type_curs;
carray[3] = NULL;
// Create the join
Dbc *join_curs;
if ((ret = automotiveDB.join(carray, &join_curs, 0)) != 0) {
    // Error handling goes here
}
// Iterate using the join cursor
while ((ret = join_curs->get(&key, &data, 0)) == 0) {
    // Do interesting things with the key and data
}
// If we exited the loop because we ran out of records,
// then it has completed successfully.
if (ret == DB_NOTFOUND) {
     // Close all our cursors and databases as is appropriate, and
     // then exit with a normal exit status (0).
}
从上面的例子我们可以看到,需要构建一个游标的 array ,并且最后一个元素是 NULL Berkeley DB 用这个 NULL 来标志 array 的结尾,从而知道 array 中有几个 cursor
Join 游标的步骤为:
1.           在第二个数据库上打开两个或者多个游标。
2.           将这些游标移动到满足你指定的条件的记录上。
3.           创建一个游标数组,大小为游标数量 +1 ,最后一个元素放入 NULL
4.           声明一个新的 cursor ,以接收 join 的结果。
5.           迭代记录。
6.           关闭这些游标。  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值