青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

SQL 開發人員 Oracle Berkeley DB 指南

常常有人問 Oracle Berkeley DB “我如何在 Berkeley DB 中進行 ?"因此,我們此處將介紹如何在 Oracle Berkeley DB 中實施眾多您喜愛的 SQL 功能。不是所有的 SQL 應用程序都應該在 Oracle Berkeley DB 實施( Oracle Berkeley DB 是一個開放源的嵌入式數據庫引擎,提供了快速、可靠、本地的持久性,無需管理),但如果您有一系列相對固定的查詢且很關心性能,Berkeley DB 將是很好的選擇。

  讓我們從頭開始 (很好的起步點)。我們從 ABC 開始學閱讀,在 Berkeley DB 中我們從術語開始。

  這里為堅定的 SQL 程序員提供了一個小型翻譯指南

SQL 術語

Oracle Berkeley DB 對應詞匯

數據庫

環境

數據庫

字節組/

/數據對

主索引

次索引

次數據庫

  選擇一個應用程序域傳統員工數據庫,經過一定的簡化。我們進一步假定您需要所有 Berkeley DB 的全部額外特性:并發、事務、可恢復性等。

  創建數據庫

  在 SQL 中,您可以執行以下命令

  CREATE DATABASE personnel

  在 Berkeley DB , 您想要創建一個放置所有應用程序數據的環境。在代碼中,您將通過一個環境句柄來引用環境,該句柄類型為 DB_ENV。您將使用這一句柄來操作此環境?,F在,將一些精妙的錯誤處理過程放在一邊,來集中討論 API?!?span lang="EN-US">

DB_ENV *dbenv;
  int ret;
  /* Create the handle. */
  DB_ASSERT(db_env_create(&dbenv, 0) == 0);
  /*
  * If you wanted to configure the environment, you would do that here.
  * Configuraition might include things like setting a cache size,
  * specifying error handling functions, specifying (different)
  * directories in which to place your log and/or data files, setting
  * parameters to describe how many locks you'd need, etc.
  */
  /* Now, open the handle. */
  DB_ASSERT(dbenv->open(dbenv, "my_databases/personnel",
  DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD, 0644);

您現在創建和打開了一個環境。需要注意幾項事情:

·                            開始前必須有 my_databases/personnel 目錄。

·                            open 調用的最后一個參數就是作為此環境的一部分為您創建的文件的模式。

·                            此處指定的標記將允許您創建環境
(DB_CREATE)
,使用鎖定 (DB_INIT_LOCK);有一個共享的內存緩存池 (DB_INIT_MPOOL);使用事務 (DB_INIT_TXN);并同時在不同的控制線程中使用得到的環境句柄 (DB_THREAD)。

  在 SQL 中,查詢通常由單獨的服務器處理,該服務器由數據庫管理員配置以在您的系統上正常(或不正常)工作。因為 Berkeley DB 嵌入到了您的應用程序中,因此該應用程序可以執行許多配置工作。但這確實與數據庫調優有關,我們將另文詳述。

  現在創建了數據庫,接下來創建一些表。在 Berkeley DB , 表由類型為 DB * 的句柄引用 。對于應用程序中的每個表,通常會打開一個句柄,然后在一或多個線程中使用該句柄。

  因此,在 SQL 中可能是  

CREATE TABLE employee
  (primary key empid int(8), last_name varchar(20), first_name varchar(15),
  salary numeric(10, 2) salary, street varchar (20), city varchar (15),
  state char(2), zip int(5))

  在我們討論實施這一過程的 Berkeley DB 代碼前,要記住在 SQL 中,數據庫負責實施和解釋數據模式,這很重要。在 Berkeley DB 中,這一解釋由應用程序完成。在分析數據操作語言 (DML) 時這將變得更加有趣,但現在其很明顯,因為在創建員工表時,Berkeley DB 只知道主鍵,不知道數據庫中的不同域。

  首先,您需要創建一個數據庫句柄來代表創建的的表。(我們再次略過錯誤處理。) 

DB *dbp;
  DB_ENV *dbenv;
  /* Let's assume we've used the code from above to set dbenv. */
  ASSERT(db_create(&dbp, dbenv, 0) == 0);
  /*
  * Like with the environment, tables can also be configured. You
  * can specify things like comparison functions, page-size, etc.
  * That would all go here.
  */
  /* Now, we'll actually open/create the primary table. */
  ASSERT(dbp->open(dbp, NULL, "employee.db", NULL, DB_BTREE,
  DB_AUTO_COMMIT | DB_CREATE | DB_THREAD, 0644) == 0).

  這一調用將使用 B-樹作為主索引結構創建表。該表將在 my_databases/personnel 目錄中物化,使用名稱 employee.db。文件將包含一個表并具有由最后的參數 (0644) 指定的文件系統權限。指定的標記在事務中創建表,允許以后的事務操作

  (DB_AUTO_COMMIT);允許表不存在時創建表 (DB_CREATE);并指定可由多個控制線程同時使用得到的句柄 (DB_THREAD)

  注意,您尚未指定具體由什么組成主鍵 (索引) 或數據字段好似存儲于該表中。這都將是應用程序的任務,稍后接觸到插入、選擇和更新部分的內容時這將變得更清楚。

現在,我們來看看如果在 employee id 上有一個主索引同時對姓使用一個次索引時將會出現什么情況。

  您應該使用上述 SQL 查詢并執行。

  CREATE INDEX lname ON employee (last_name)

  在 Berkeley DB 中,次索引就像是表。然后您可以聯合表,使一個表成為另一個表的次索引。為實施這一功能,需要更深入地了解應用程序要使用的數據表示。

  假設應用程序要使用 C 結構以在我們的員工表中包含字節組。您可以按下面所示定義結構: 

typedef struct _emp_data {
  char lname[20];
  char fname[15];
  float salary;
  char street[20];
  char city[15];
  char state[2];
  int zip;
  } emp_data;

  假設員工 ID 為簡單的整數:

  typedef int emp_key;

  在 Berkeley DB 中,操作鍵或數據項時,您使用 DBT 結構。DBT 包含了不透明的字節串,以指針和長度來表示。指針由 DBT 的數據字段引用,長度存儲于 DBT 的大小字段中。如果希望操縱表示一個員工的鍵/數據對,您需要將一個 DBT 用于 emp_key,另一個用于 emp_data。  

DBT key_dbt, data_dbt;
  emp_key ekey;
  emp_data edata;
  memset(&key_dbt, 0, sizeof(key_dbt));
  memset(&data_dbt, 0, sizeof(data_dbt));
  /*
  * Now make the key and data DBT's reference the key and data
  * variables.
  */
  key_dbt.data = &ekey;
  key_dbt.size = sizeof(ekey);
  data_dbt.data = &edata;
  data_dbt.size = sizeof(edata);

  這里我們可以了解到 SQL 中的字節組由鍵/數據對表示,應用程序負責了解如何解釋這些對。

 

有了這些作為背景后,我們返回到次索引的討論。因為 Berkeley DB 不了解鍵/數據對中數據元素的模式和結構,所以需要應用程序的幫助來找到我們用作次索引的字段。應用程序以回調函數方式提供幫助。回調函數接受鍵/數據對輸入并返回引用了用作次鍵的值的 DBT

所以要創建 last_name 的次索引,必須編寫一個回調函數,接受鍵/數據對輸入并返回引用了數據項的 last_name 字段的 DBT?! ?span lang="EN-US">

int
  lname_callback(DB *dbp, const DBT *key, const DBT *data, DBT *skey)
  {
  emp_data *edata;
  /*
  * We know that the opaque byte-string represented by the data DBT
  * represents one of our emp_data structures, so let's cast it
  * to one of those so that we can manipulate it.
  */
  edata = data->data;
  skey->data = edata->lname;
  skey->size = strlen((edata->lname);
  return (0);
  }

  寫完回調函數后,可以指定次索引。次索引只是一個表,所以先創建一個表:  

DB *sdbp;
  ASSERT(db_create(&sdbp, dbenv, 0) == 0);
  /* Configure sdbp. */
  ASSERT(sdbp->open(sdbp, NULL, "emp_lname.db", NULL, DB_BTREE,
  DB_AUTO_COMMIT | DB_CREATE | DB_THREAD, 0644) == 0);

  再次使用 B 樹結構對姓進行索引,保留以前使用的所有標記和模式。

  最后,您必須將次索引表與主表(員工表)相關聯。請記住,dbp 是員工表的句柄, sdbp 是次索引表的句柄。

  ASSERT(dbp->associate(dbp, NULL, sdbp, lname_callback, flags) == 0);

  注意事項:

·                            可以了創建任意多的次索引。重要的問題是次索引降低了插入的速度 (因為您必須為每個次索引創建索引項),但如果使用次鍵值(如,姓)來查詢和選擇字節組, 它們將大大改進查詢的性能。

·                            在任何時候更新主表時,只要打開并關聯了次索引,次索引將始終保持最新。但如果忘記打開并關聯次索引,然后更改基表,您會發現次索引不是最新的。

  應當避免這一情況。

  DDL 中的最后兩個操作是丟棄命令:丟棄索引、表和數據庫。

  如同在 SQL 中丟棄索引和刪除表一樣,您也能在 Berkeley DB 中完成這些操作。在 SQL 中,您可以執行以下命令

  DROP TABLE employee

  或者

  DROP INDEX lname

SQL 中丟棄一個表將丟棄與之關聯的所有索引,在 Berkeley DB 中,您必須顯式完成此任務。幸運的是,在 Berkeley DB 中丟棄表或索引是同樣的操作。

  移除表前,必須關閉表上的所有數據庫句柄。關閉表容易;假設我們要丟棄員工數據庫的次索引。先關閉次索引:

  sdbp->close(sdbp, 0)

  在發出數據庫句柄的關閉命令后,不能再使用句柄。

  關閉次索引表后,您可以使用 dbenv 句柄的 dbremove 方法將其移除:  

DB_ENV *dbenv;
  ASSERT(dbenv->dbremove(dbenv,
  NULL, "emp_lname.db", NULL, DB_AUTO_COMMIT) == 0);

  可以使用同一調用順序 (closing dbremoving) 來丟棄表。

  假設不想丟棄表,只想更改其名稱。您也可完成這一操作。

  與移除一樣,首先要關閉表句柄:

  dbp->close(dbp, 0);

  現在您可以更改表名稱:  

DB_ENV *dbenv;
  ASSERT(dbenv->dbrename(dbenv,
  NULL, "employee.db", NULL, "newemp.db", DB_AUTO_COMMIT) == 0);

  最后,您可能想銷毀數據庫。在 SQL 中執行

  DROP DATABASE personnel

  這一命令在 Berkeley DB 中也有對應的命令。

  首先,必須關閉環境:

  ASSERT(dbenv->close(dbenv, 0) == 0);

  與關閉表句柄一樣,當關閉環境句柄后,將不能使用該句柄。所以,為了丟棄表,您需要創建一個新句柄,然后使用該句柄移除數據庫(環境)。 

ASSERT(db_env_create(&dbenv, 0) == 0);
  ASSERT(dbenv->remove(dbenv, "my_databases/personnel", 0) == 0);

  至此,我們完成了 SQL DDL Berkeley DB 的轉換。接下來,我們將討論如何完成 SQL DML Berkeley DB 的轉換。

  在 Berkeley DB 中執行 SQL DML 操作

  我們已經介紹了 SQL DDL 和其在 Berkeley DB 中的實現,現在要將數據添加到數據庫,討論 SQL 的插入、更新和刪除。

  在 SQL 中使用插入語句將數據插入表:  

INSERT INTO employees VALUES (00010002, "mouse", "mickey", 1000000.00,
  "Main Street", "Disney Land", "CA", 98765);

  SQL 插入都變成了數據庫或游標句柄的 Berkeley DB“put”方法;我們先討論數據庫,然后再探討游標。

  假設您已經打開了一個表,有一個數據庫句柄 dbp 引用了員工表?,F在,雇傭 Mickey Mouse。

DB *dbp;
  DBT key_dbt, data_dbt;
  emp_data edata;
  emp_key ekey;
  /* Put the value into the employee key. */
  ekey = 00010002;
  /* Initialize an emp_data structure. */
  strcpy(edata.lname, "Mouse");
  strcpy(edata.fname, "Mickey");
  edata.salary = 1000000.00;
  strcpy(edata.street, "Main Street");
  strcpy(edata.city, "Disney Land");
  strcpy(edata.state, "CA");
  edata.zip = 98765;
  /* Initialize DBTs */
  memset(&key_dbt, 0, sizeof(key_dbt));
  memset(&data_dbt, 0, sizeof(data_dbt));
  /* Now, assign key and data values to DBTs. */
  key->data = &ekey;
  key->size = sizeof(ekey);
  data->data = &edata;
  data->size = sizeof(edata);
  /* Finally, put the data into the database. */
  ASSERT(dbp->put(dbp, NULL, &key_dbt, &data_dbt, DB_AUTO_COMMIT) == 0);

  請注意,如果已經有將任何次索引與員工表相關聯(如在 SQL ),則在插入時將自動對其進行更新。

  現在,假設表中有些數據,您希望對這些數據進行更改。例如,要給 Mickey 漲工資!有多種完成方法。

 

第一個方法與上面的插入代碼一樣如果您在一個表上使用 PUT 方法并且該鍵已存在 (且表不允許單鍵有相同的數值), PUT 將使用新版本代替舊版本。因此,以下步驟將使用新記錄替換 Mickey 的記錄,薪水將為 $2,000,000,而不是 $1,000,000?! ?span lang="EN-US">

/* Put the value into the employee key. */
  ekey = 00010002;
  /* Initialize an emp_data structure. */
  strcpy(edata.lname, "Mouse");
  strcpy(edata.fname, "Mickey");
  edata.salary = 2000000.00;
  strcpy(edata.street, "Main Street");
  strcpy(edata.city, "Disney Land");
  strcpy(edata.state, "CA");
  edata.zip = 98765;
  /* Initialize DBTs */
  memset(&key_dbt, 0, sizeof(key_dbt));
  memset(&data_dbt, 0, sizeof(data_dbt));
  /* Now, assign key and data values to DBTs. */
  key->data = &ekey;
  key->size = sizeof(ekey);
  data->data = &edata;
  data->size = sizeof(edata);
  /* Finally, put the data into the database. */
  ASSERT(dbp->put(dbp, NULL, &key_dbt, &data_dbt, DB_AUTO_COMMIT) == 0);

請注意,該方法較麻煩,為完成它,您需要了解數據庫中所有其他域的值。因此,不同于

  UPDATE employees SET salary = 2000000 WHERE empid = 000100002

  其中,您只需知曉 employee ID,而現在需要知曉所有信息。難道在 Berkeley DB 沒有可用方法嗎?答是是有。如果確切地知道要替換的數據項字節,您可以使用與等同于更新命令的方法。

  要使用此方法,您需要引入游標概念。游標表示表中的某個位置。它讓您遍歷表并保留當前項的情況,然后再對其操作。

  在 Berkeley DB 中創建游標很簡單它是數據庫句柄的方法:  

DBC *dbc;
  DB *dbp;
  ASSERT(dbp->cursor(dbp, NULL, 0) == 0);

  有游標后,我們需要將其定位于 Mickey 的記錄,以便能對其進行更新。這等同于 SQL 語句的 WHERE 部分?! ?span lang="EN-US">

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, set the cursor to the record with the key emp_key. */
  dbc->c_get(dbc, &key_dbt, &data_dbt, DB_SET);

  接下來我們就可以更改薪水了 (處理子句的“SET salary=2000000”部分)  

/* Change the salary. */
  edata = data_dbt->data;
  edata.salary = 2000000;

  最后,應用 SQL 語句的 UPDATE 部分:

  dbc->c_put(dbc, &key_dbt, &data_dbt, DB_CURRENT);

在本例中,您事先不知道 Mickey 的記錄內容,因此需要檢索然后再更新。

  或者,甚至無需檢索記錄。DBT 上的 DB_DBT_PARTIAL 標記值指示您在獲取/插入記錄的一部分,所以 Berkeley DB 可以忽略除該部分外的所有內容。

  再試一次:  

emp_data edata;
  float salary;
  /* 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);

  不檢索整個記錄,不檢索任何東西即執行 PARTIAL 獲取,指定您只需要 0 字節的數據項?! ?span lang="EN-US">

/* We don't want the data, we just want to position the cursor. */
  memset(&data_dbt, 0, sizeof(data_dbt));
  data_dbt->flags = DB_DBT_PARTIAL;
  data_dbt->dlen = 0;
  /* Position the cursor on Mickey's record */
  dbc->c_get(dbc, &key_dbt, &data_dbt, DB_SET);
  /*
  * Now, prepare for a partial put. Note that the DBT has already
  * been initialized for partial operations. We need to specify
  * where in the data item we wish to place the new bytes and
  * how many bytes we'd like to replace.
  */
  salary = 2000000.00;
  /* The DBT contains just the salary information. */
  data_dbt->data = &salary;
  data_dbt->size = sizeof(salary);
  /*
  * dlen and doff tell Berkeley DB where to place this information
  * in the record. dlen indicates how many bytes we are replacing --
  * in this case we're replacing the length of the salary field in
  * the structure (sizeof(emp_data.salary)). doff indicates where
  * in the data record we will place these new bytes -- we need to
  * compute the offset of the salary field.
  */
  data_dbt->dlen = sizeof(emp_data.salary);
  data_dbt->doff = ((char *)&edata.salary - (char *)&edata);
  /* Now, put the record back with the new data. */
  dbc->c_put(dbc, &key_dbt, &data_dbt, DB_CURRENT);

數據檢索

  了解如何向表插入數據后,現在學習如何檢索它。讓我們從最簡單的方法開始:根據其主鍵查找值。

  SELECT * FROM employees WHERE id=0010002

  您已經知道如何使用游標來完成此任務:  

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, set the cursor to the record with the key emp_key. */
  dbc->c_get(dbc, &key_dbt, &data_dbt, DB_SET);

 

使用上面的游標操作,因為我們稍后要更新該記錄。假如只想檢索記錄,則甚至不需要游標。所需要的是 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) 應用程序必須檢查循環內范圍的終點。

 

posted on 2011-08-28 18:33 肥仔 閱讀(611) 評論(0)  編輯 收藏 引用 所屬分類: 數據庫

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日一区二区三区在线观看国产免| 欧美激情综合色| 亚洲精品视频免费| 国产在线欧美日韩| 欧美亚洲不卡| 欧美日韩不卡| 欧美精品色网| 欧美午夜精品久久久久久人妖| 看欧美日韩国产| 午夜天堂精品久久久久| 亚洲深夜av| 亚洲欧美激情四射在线日| 在线午夜精品| 欧美亚洲免费在线| 校园激情久久| 麻豆免费精品视频| 欧美精品午夜视频| 国产精品毛片a∨一区二区三区| 国产精品久久久久aaaa| 精品不卡一区二区三区| 亚洲欧美999| 久久久水蜜桃| 欧美日韩一区二区三区高清| 国产精品亚洲综合久久| 亚洲国产高清一区二区三区| 亚洲精品一区二区三区福利| 午夜视频在线观看一区| 欧美二区不卡| 香蕉久久一区二区不卡无毒影院 | 国产精品综合久久久| 国产视频欧美视频| 亚洲精品一区二区三区在线观看 | 欧美一区1区三区3区公司| 亚洲国内精品| 韩国一区二区三区在线观看| 欧美中文字幕久久| 久久精品欧美日韩| 国产精品久久久| 亚洲国产一区二区三区在线播 | 久久久噜噜噜久久中文字免| 欧美在线资源| 亚洲素人一区二区| 欧美经典一区二区三区| 亚洲国产美国国产综合一区二区| 亚洲欧美中文日韩在线| 亚洲一区免费看| 欧美成人高清视频| 久久成人av少妇免费| 亚洲男人第一av网站| 久久9热精品视频| 亚洲高清在线视频| 亚洲第一天堂av| 欧美日韩八区| 六月丁香综合| 欧美日韩中文字幕日韩欧美| 亚洲欧美国产精品桃花| 欧美影院视频| 一区二区三区四区国产精品| 午夜精品国产更新| 亚洲国产精品久久久久婷婷884 | 亚洲午夜免费视频| 国产精品丝袜白浆摸在线| 久久亚洲二区| 国产精品第三页| 老鸭窝亚洲一区二区三区| 国产精品va| 欧美国产在线观看| 国语自产精品视频在线看一大j8 | 国产精品视频一区二区高潮| 久久久精品欧美丰满| 欧美日韩国产欧| 欧美成人免费va影院高清| 国产精品久久国产三级国电话系列| 欧美成年网站| 性欧美大战久久久久久久久| 9国产精品视频| 免费观看不卡av| 欧美成人免费在线观看| 加勒比av一区二区| 久久成人综合网| 久久久中精品2020中文| 国产亚洲在线| 免费成人在线视频网站| 欧美自拍丝袜亚洲| 国产精品亚洲综合色区韩国| 亚洲视屏在线播放| 久久激情网站| 亚洲国产成人在线视频| 美女黄毛**国产精品啪啪| 亚洲第一色中文字幕| 一区二区三区四区国产精品| 国产精品扒开腿做爽爽爽视频| 一区二区动漫| 欧美中文字幕视频| 亚洲国产精品免费| 欧美日韩免费观看一区三区| 一区二区三区四区五区精品视频| 欧美一区二区在线免费观看| 影音国产精品| 国产精品一区视频网站| 久久在线视频在线| 亚洲一区二区3| 亚洲国产日本| 欧美大片免费观看| 欧美一区二区国产| 亚洲免费视频成人| 在线看一区二区| 国产情人节一区| 国产精品乱码久久久久久| 欧美不卡一卡二卡免费版| 欧美亚洲网站| 欧美在线91| 欧美亚洲综合久久| 日韩一级视频免费观看在线| 国内综合精品午夜久久资源| 国产精品国产三级国产aⅴ9色| 免费欧美日韩| 老司机精品久久| 欧美国产日产韩国视频| 久久久噜噜噜久久人人看| 欧美一级日韩一级| 久久久亚洲国产天美传媒修理工| 亚洲欧美激情一区二区| 久久不见久久见免费视频1| 亚洲欧美在线视频观看| 西西裸体人体做爰大胆久久久| 西瓜成人精品人成网站| 欧美自拍偷拍| 欧美国产第一页| 欧美视频一区二区三区…| 亚洲精品1区| 国产精品露脸自拍| 久久久久免费观看| 欧美国产日本| 亚洲一区激情| 亚洲精品日韩综合观看成人91| 老色鬼久久亚洲一区二区| 亚洲国产免费| 亚洲素人在线| 欧美刺激性大交免费视频| 国产精品亚洲视频| 亚洲毛片在线观看.| 久久久久久9| 一区二区三区视频免费在线观看| 夜夜爽夜夜爽精品视频| 久久九九热免费视频| 国产精品国产a| 欧美福利在线| 欧美日韩天天操| 亚洲欧洲美洲综合色网| 性欧美xxxx大乳国产app| 欧美激情小视频| 久久99伊人| 依依成人综合视频| 国产视频在线一区二区| 国模叶桐国产精品一区| 亚洲日本欧美| 在线一区免费观看| 久久免费的精品国产v∧| 国产在线成人| 亚洲摸下面视频| 亚洲性图久久| 亚洲国产一区视频| 99国产精品国产精品毛片| 乱中年女人伦av一区二区| 亚洲欧洲在线免费| 亚洲人成欧美中文字幕| 欧美日韩麻豆| 久久精品1区| 欧美va天堂在线| 亚洲一区二区三区成人在线视频精品| 9久re热视频在线精品| 国产精品www994| 久久综合网hezyo| 欧美日韩国产首页在线观看| 亚洲综合第一| 久久精品中文字幕一区| 亚洲区国产区| 国产精品一区久久久| 久久人人爽人人爽爽久久| 欧美在线观看一区二区| 亚洲精品日本| 久久国产主播精品| 亚洲欧美日韩一区二区三区在线观看 | 欧美国产先锋| 国产精品毛片一区二区三区| 免费人成网站在线观看欧美高清 | 亚洲欧美日韩综合一区| 亚洲激情av| 欧美在线免费看| 欧美体内she精视频在线观看| 鲁大师影院一区二区三区| 国产精品视频一区二区高潮| 亚洲三级性片| 一区二区三区久久久| 欧美日韩国产综合一区二区| 亚洲激情视频| 亚洲欧美日韩成人| 欧美视频中文字幕| 免费视频久久|