POP Article V2.0 设为主页
收藏本站
首 页交流论坛留 言
您现在的位置:首 页 >> 热门开源项目 >> Berkeley DB >> 查看文章
Oracle Berkeley DB 指南(4)
作者:tamsyn  来源:www.sqlite.com.cn  时间:2007-11-22  【 字体: 】 〖 双击滚屏 〗

使用上面的游标操作,因为我们稍后要更新该记录。假如只想检索记录,则甚至不需要游标。所需要的是 dbp 句柄的 get 方法:  

DBT key_dbt, data_dbt;
  emp_data *edata;
  emp_key ekey;
  /* We'd like to look up Mickey's key. */
  emp_key = 0010002;
  memset(&key_dbt, 0, sizeof(key_dbt));
  key_dbt.data = &emp_key;
  key_dbt.size = sizeof(emp_key);
  /*
  * We want the data returned, so we don't need to initialize the
  * employee data data structure.
  */
  memset(&data_dbt, 0, sizeof(data_dbt));
  /* Now, use the dbp method. */
  dbp->get(dbp, NULL, &key_dbt, &data_dbt, 0);

  因此,这与上面的 SELECT 表达式一样。

  到目前为止,我们都是根据主键来查找记录。如果不知道主键,该怎么办?下面提供了几种方法:

使用次键值查找记录。

  遍历共享同一键的项目。

  遍历整个数据库。

  下面详述以上方法。

  使用次键

  与在 SQL 中一样,根据次键检索和使用主键非常类似。

  事实上,SQL 查询看起来相同,除了 where 子句:

  SELECT * FROM employees WHERE last_name = "Mouse"

  Berkeley DB 调用与其对等的主键调用类似。

  它使用的不是主键示例中的 dbp,而是使用 sdbp 根据次键来进行查找:  

DBT key_dbt, data_dbt;
  emp_data *edata;
  /* We'd like to look up by Mickey's last name. */
  memset(&key_dbt, 0, sizeof(key_dbt));
  key_dbt.data = "Mouse";
  key_dbt.size = strlen((char *)key_dbt.data);
  /*
  * We want the data returned, so we don't need to initialize the
  * employee data data structure.
  */
  memset(&data_dbt, 0, sizeof(data_dbt));
  /* Now, call the get method. */
  sdbp->get(sdbp, NULL, &key_dbt, &data_dbt, 0);

  data_dbt 中返回的内容非常有趣。返回的是主数据库中的数据即在数据 DBT 中返回了同样的东西,不管您是使用主键还是次键查找。

  但是,您会发现按次键查找时,得到的结果与按主键检索或 SQL 语句得到的结果有所不同。主键丢失,因为没有位置来返回它。所以,上面的代码实际上实施  

SELECT last_name, first_name, salary, street, city, state, zip FROM
  employees WHERE last_name="Mouse"

  如果您需要主键,该如何做?答案是使用 dbp->pget dbc->pget 方法。这两个方法与 get 方法一样,只是它们专门设计用于您需要返回主键时的次索引查询。因此,在这一情形中,结果中会包括主键、次键和数据元素:

DBT key_dbt, pkey_dbt, data_dbt;
  emp_data *edata;
  /* We'd like to look up by Mickey's last name. */
  memset(&key_dbt, 0, sizeof(key_dbt));
  key_dbt.data = "Mouse";
  key_dbt.size = strlen((char *)key_dbt.data);
  /* Set up the dbt into which to return the primary. */
  memset(&pkey_dbt, 0, sizeof(pkey_dbt));
  /*
  * We want the data returned, so we don't need to initialize the
  * employee data data structure.
  */
  memset(&data_dbt, 0, sizeof(data_dbt));
  /* Now, get the record and the primary key. */
  sdbp->pget(sdbp, NULL, &key_dbt, &pkey_dbt, &data_dbt, 0);

  该代码等同于 SQL 次选择:

  SELECT * FROM employees WHERE last_name="Mouse"

  遍历多个记录

  到现在为止,我们仅返回了一个记录。SQL 允许您返回多个记录 (换言之,姓为 Mouse 的所有员工)。如何在 Berkeley DB 中实现此目的?

  让我们考虑两种情形。第一个情形,按照键来查找项目。第二个情形,搜索数据库,按照不带键的字段查找项目。

  假设您希望查找所有姓 Mouse 的员工(假设有多个)。这意味着已经创建了 last_name 次索引,从而允许重复。打开数据库前,需要对它进行配置以支持重复:  

sdbp->set_flags(sdbp, DB_DUP);
  ASSERT(sdbp->open(sdbp, NULL, "emp_lname.db", NULL, DB_BTREE,
  DB_AUTO_COMMIT | DB_CREATE | DB_THREAD, 0644) == 0);

  现在,按次索引检索时,您可能想使用游标来完成。开始时使用前面使用的代码,可以添加一个循环以遍历共享同一次键的项目: 

DBT key_dbt, data_dbt;
  DBC *sdc;
  emp_data *edata;
  /* We'd like to look up by Mickey's last name. */
  memset(&key_dbt, 0, sizeof(key_dbt));
  key_dbt.data = "Mouse";
  key_dbt.size = strlen((char *)key_dbt.data);
  /*
  * We want the data and primary key returned, so we need only
  * initialize the DBTs for them to be returned.
  */
  memset(&data_dbt, 0, sizeof(data_dbt));
  memset(&pkey_dbt, 0, sizeof(pkey_dbt));
  /* Now, create a cursor. */
  sdbp->cursor(sdbp, NULL, &sdbc, 0);
  /* Now loop over all items with the specified key. */
  for (ret = sdbc->pget(sdbc, &key_dbt, &pkey_dbt, &data_dbt, DB_SET);
  ret == 0:
  ret = sdbc->pget(sdbc, &key_dbt, &pkey_dbt, &data_dbt, DB_NEXT_DUP) {
  /* Do per-record processing in here. */
  }

通过使用游标查找带指定键的第一个项目,完成游标的初始化,然后遍历数据库中带同一键的所有项目。

  另一个可能的根据键进行遍历的形式为查询形式,如

  SELECT * FROM employees WHERE id >= 1000000 AND id < 2000000

  再次使用游标来遍历,但这一次您想创建一个起始和结束点。Berkeley DB 使得起始点的建立非常简单,结束点由应用程序来完成。  

DBT key_dbt, data_dbt;
  DBC *dc;
  emp_key ekey;
  /* Set the starting point. */
  memset(&key_dbt, 0, sizeof(key_dbt));
  ekey = 1000000;
  key_dbt.data = &ekey;
  key_dbt.size = sizeof(ekey);
  key_dbt.flags = DB_DBT_USERMEM;
  key_dbt.ulen = sizeof(ekey);
  memset(&data_dbt, 0, sizeof(data_dbt));
  /* Now, create a cursor. */
  dbp->cursor(dbp, NULL, &dbc, 0);
  /* Now loop over items starting with the low key. */
  for (ret = dbc->get(dbc, &key_dbt, &data_dbt, DB_SET_RANGE);
  ret == 0:
  ret = dbc->get(dbc, &key_dbt, &data_dbt, DB_NEXT)) {
  /* Check if we are still in the range. */
  if (ekey >= 2000000)
  break;
  /* Do per-record processing in here. */
  }

  要注意两点:1) DB_SET_RANGE 标记作为循环的开始,这会将游标定位于第一个大于或等于指定键的项目; 2) 应用程序必须检查循环内范围的终点。

浏览次数:   【 打 印 】【 关 闭
上一篇:Oracle Berkeley DB 指南(3)
下一篇:Oracle Berkeley DB 指南(2)
 论坛登陆
用户名:
密  码:
验证码: 
Cookie 选项:
正常登陆 隐身登陆
   
没有注册?
 文章搜索
 推荐文章
 酷站推荐
 热门文章
 网站统计
关于我们 | 网站地图 | 联系我们 | 网站历史 | 友情链接 | TOP
Copyright© 2006 Sqlite中文社区  程序开发: mistletoe  站长: 林轩 陈文成