|
|
|
|
|
| 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)
|
|
|
|
|
|
|
|
| 论坛登陆 |
| 文章搜索 |
|
| 推荐文章 |
|
| 酷站推荐 |
|
|
| 热门文章 |
|
| 网站统计 |
|
|
|