• <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>

            woaidongmao

            文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評(píng)論 - 661, 引用 - 0
            數(shù)據(jù)加載中……

            SQL 開發(fā)人員 Oracle Berkeley DB 指南

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

              讓我們從頭開始 (很好的起步點(diǎn))。我們從 ABC 開始學(xué)閱讀,在 Berkeley DB 中我們從術(shù)語開始。

              這里為堅(jiān)定的 SQL 程序員提供了一個(gè)小型翻譯指南

            SQL 術(shù)語

            Oracle Berkeley DB 對(duì)應(yīng)詞匯

            數(shù)據(jù)庫

            環(huán)境

            數(shù)據(jù)庫

            字節(jié)組/

            /數(shù)據(jù)對(duì)

            主索引

            次索引

            次數(shù)據(jù)庫

              選擇一個(gè)應(yīng)用程序域傳統(tǒng)員工數(shù)據(jù)庫,經(jīng)過一定的簡化。我們進(jìn)一步假定您需要所有 Berkeley DB 的全部額外特性:并發(fā)、事務(wù)、可恢復(fù)性等。

              創(chuàng)建數(shù)據(jù)庫

              在 SQL 中,您可以執(zhí)行以下命令

              CREATE DATABASE personnel

              在 Berkeley DB , 您想要?jiǎng)?chuàng)建一個(gè)放置所有應(yīng)用程序數(shù)據(jù)的環(huán)境。在代碼中,您將通過一個(gè)環(huán)境句柄來引用環(huán)境,該句柄類型為 DB_ENV。您將使用這一句柄來操作此環(huán)境。現(xiàn)在,將一些精妙的錯(cuò)誤處理過程放在一邊,來集中討論 API。 

            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);

            您現(xiàn)在創(chuàng)建和打開了一個(gè)環(huán)境。需要注意幾項(xiàng)事情:

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

            ·                            open 調(diào)用的最后一個(gè)參數(shù)就是作為此環(huán)境的一部分為您創(chuàng)建的文件的模式。

            ·                            此處指定的標(biāo)記將允許您創(chuàng)建環(huán)境
            (DB_CREATE)
            ,使用鎖定 (DB_INIT_LOCK);有一個(gè)共享的內(nèi)存緩存池 (DB_INIT_MPOOL);使用事務(wù) (DB_INIT_TXN);并同時(shí)在不同的控制線程中使用得到的環(huán)境句柄 (DB_THREAD)

              在 SQL 中,查詢通常由單獨(dú)的服務(wù)器處理,該服務(wù)器由數(shù)據(jù)庫管理員配置以在您的系統(tǒng)上正常(或不正常)工作。因?yàn)?span lang="EN-US"> Berkeley DB 嵌入到了您的應(yīng)用程序中,因此該應(yīng)用程序可以執(zhí)行許多配置工作。但這確實(shí)與數(shù)據(jù)庫調(diào)優(yōu)有關(guān),我們將另文詳述。

              現(xiàn)在創(chuàng)建了數(shù)據(jù)庫,接下來創(chuàng)建一些表。在 Berkeley DB , 表由類型為 DB * 的句柄引用 。對(duì)于應(yīng)用程序中的每個(gè)表,通常會(huì)打開一個(gè)句柄,然后在一或多個(gè)線程中使用該句柄。

              因此,在 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))

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

              首先,您需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)庫句柄來代表創(chuàng)建的的表。(我們?cè)俅温赃^錯(cuò)誤處理。) 

            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).

              這一調(diào)用將使用 B-樹作為主索引結(jié)構(gòu)創(chuàng)建表。該表將在 my_databases/personnel 目錄中物化,使用名稱 employee.db。文件將包含一個(gè)表并具有由最后的參數(shù) (0644) 指定的文件系統(tǒng)權(quán)限。指定的標(biāo)記在事務(wù)中創(chuàng)建表,允許以后的事務(wù)操作

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

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

            現(xiàn)在,我們來看看如果在 employee id 上有一個(gè)主索引同時(shí)對(duì)姓使用一個(gè)次索引時(shí)將會(huì)出現(xiàn)什么情況。

              您應(yīng)該使用上述 SQL 查詢并執(zhí)行。

              CREATE INDEX lname ON employee (last_name)

              在 Berkeley DB 中,次索引就像是表。然后您可以聯(lián)合表,使一個(gè)表成為另一個(gè)表的次索引。為實(shí)施這一功能,需要更深入地了解應(yīng)用程序要使用的數(shù)據(jù)表示。

              假設(shè)應(yīng)用程序要使用 C 結(jié)構(gòu)以在我們的員工表中包含字節(jié)組。您可以按下面所示定義結(jié)構(gòu): 

            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;

              假設(shè)員工 ID 為簡單的整數(shù):

              typedef int emp_key;

              在 Berkeley DB 中,操作鍵或數(shù)據(jù)項(xiàng)時(shí),您使用 DBT 結(jié)構(gòu)。DBT 包含了不透明的字節(jié)串,以指針和長度來表示。指針由 DBT 的數(shù)據(jù)字段引用,長度存儲(chǔ)于 DBT 的大小字段中。如果希望操縱表示一個(gè)員工的鍵/數(shù)據(jù)對(duì),您需要將一個(gè) DBT 用于 emp_key,另一個(gè)用于 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 中的字節(jié)組由鍵/數(shù)據(jù)對(duì)表示,應(yīng)用程序負(fù)責(zé)了解如何解釋這些對(duì)。

             

            有了這些作為背景后,我們返回到次索引的討論。因?yàn)?span lang="EN-US"> Berkeley DB 不了解鍵/數(shù)據(jù)對(duì)中數(shù)據(jù)元素的模式和結(jié)構(gòu),所以需要應(yīng)用程序的幫助來找到我們用作次索引的字段。應(yīng)用程序以回調(diào)函數(shù)方式提供幫助。回調(diào)函數(shù)接受鍵/數(shù)據(jù)對(duì)輸入并返回引用了用作次鍵的值的 DBT

            所以要?jiǎng)?chuàng)建 last_name 的次索引,必須編寫一個(gè)回調(diào)函數(shù),接受鍵/數(shù)據(jù)對(duì)輸入并返回引用了數(shù)據(jù)項(xiàng)的 last_name 字段的 DBT。  

            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);
              }

              寫完回調(diào)函數(shù)后,可以指定次索引。次索引只是一個(gè)表,所以先創(chuàng)建一個(gè)表:  

            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 樹結(jié)構(gòu)對(duì)姓進(jìn)行索引,保留以前使用的所有標(biāo)記和模式。

              最后,您必須將次索引表與主表(員工表)相關(guān)聯(lián)。請(qǐng)記住,dbp 是員工表的句柄, sdbp 是次索引表的句柄。

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

              注意事項(xiàng):

            ·                            可以了創(chuàng)建任意多的次索引。重要的問題是次索引降低了插入的速度 (因?yàn)槟仨殲槊總€(gè)次索引創(chuàng)建索引項(xiàng)),但如果使用次鍵值(如,姓)來查詢和選擇字節(jié)組, 它們將大大改進(jìn)查詢的性能。

            ·                            在任何時(shí)候更新主表時(shí),只要打開并關(guān)聯(lián)了次索引,次索引將始終保持最新。但如果忘記打開并關(guān)聯(lián)次索引,然后更改基表,您會(huì)發(fā)現(xiàn)次索引不是最新的。

              應(yīng)當(dāng)避免這一情況。

              DDL 中的最后兩個(gè)操作是丟棄命令:丟棄索引、表和數(shù)據(jù)庫。

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

              DROP TABLE employee

              或者

              DROP INDEX lname

            SQL 中丟棄一個(gè)表將丟棄與之關(guān)聯(lián)的所有索引,在 Berkeley DB 中,您必須顯式完成此任務(wù)。幸運(yùn)的是,在 Berkeley DB 中丟棄表或索引是同樣的操作。

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

              sdbp->close(sdbp, 0)

              在發(fā)出數(shù)據(jù)庫句柄的關(guān)閉命令后,不能再使用句柄。

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

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

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

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

              與移除一樣,首先要關(guān)閉表句柄:

              dbp->close(dbp, 0);

              現(xiàn)在您可以更改表名稱:  

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

              最后,您可能想銷毀數(shù)據(jù)庫。在 SQL 中執(zhí)行

              DROP DATABASE personnel

              這一命令在 Berkeley DB 中也有對(duì)應(yīng)的命令。

              首先,必須關(guān)閉環(huán)境:

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

              與關(guān)閉表句柄一樣,當(dāng)關(guān)閉環(huán)境句柄后,將不能使用該句柄。所以,為了丟棄表,您需要?jiǎng)?chuàng)建一個(gè)新句柄,然后使用該句柄移除數(shù)據(jù)庫(環(huán)境)。 

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

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

              在 Berkeley DB 中執(zhí)行 SQL DML 操作

              我們已經(jīng)介紹了 SQL DDL 和其在 Berkeley DB 中的實(shí)現(xiàn),現(xiàn)在要將數(shù)據(jù)添加到數(shù)據(jù)庫,討論 SQL 的插入、更新和刪除。

              在 SQL 中使用插入語句將數(shù)據(jù)插入表:  

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

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

              假設(shè)您已經(jīng)打開了一個(gè)表,有一個(gè)數(shù)據(jù)庫句柄 dbp 引用了員工表。現(xiàn)在,雇傭 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);

              請(qǐng)注意,如果已經(jīng)有將任何次索引與員工表相關(guān)聯(lián)(如在 SQL ),則在插入時(shí)將自動(dòng)對(duì)其進(jìn)行更新。

              現(xiàn)在,假設(shè)表中有些數(shù)據(jù),您希望對(duì)這些數(shù)據(jù)進(jìn)行更改。例如,要給 Mickey 漲工資!有多種完成方法。

             

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

            /* 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);

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

              UPDATE employees SET salary = 2000000 WHERE empid = 000100002

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

              要使用此方法,您需要引入游標(biāo)概念。游標(biāo)表示表中的某個(gè)位置。它讓您遍歷表并保留當(dāng)前項(xiàng)的情況,然后再對(duì)其操作。

              在 Berkeley DB 中創(chuàng)建游標(biāo)很簡單它是數(shù)據(jù)庫句柄的方法:  

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

              有游標(biāo)后,我們需要將其定位于 Mickey 的記錄,以便能對(duì)其進(jìn)行更新。這等同于 SQL 語句的 WHERE 部分。  

            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;

              最后,應(yīng)用 SQL 語句的 UPDATE 部分:

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

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

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

              再試一次:  

            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);

              不檢索整個(gè)記錄,不檢索任何東西即執(zhí)行 PARTIAL 獲取,指定您只需要 0 字節(jié)的數(shù)據(jù)項(xiàng)。  

            /* 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);

            數(shù)據(jù)檢索

              了解如何向表插入數(shù)據(jù)后,現(xiàn)在學(xué)習(xí)如何檢索它。讓我們從最簡單的方法開始:根據(jù)其主鍵查找值。

              SELECT * FROM employees WHERE id=0010002

              您已經(jīng)知道如何使用游標(biāo)來完成此任務(wù):  

            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);

             

            使用上面的游標(biāo)操作,因?yàn)槲覀兩院笠略撚涗洝<偃缰幌霗z索記錄,則甚至不需要游標(biāo)。所需要的是 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 表達(dá)式一樣。

              到目前為止,我們都是根據(jù)主鍵來查找記錄。如果不知道主鍵,該怎么辦?下面提供了幾種方法:

            使用次鍵值查找記錄。

              遍歷共享同一鍵的項(xiàng)目。

              遍歷整個(gè)數(shù)據(jù)庫。

              下面詳述以上方法。

              使用次鍵

              與在 SQL 中一樣,根據(jù)次鍵檢索和使用主鍵非常類似。

              事實(shí)上,SQL 查詢看起來相同,除了 where 子句:

              SELECT * FROM employees WHERE last_name = "Mouse"

              Berkeley DB 調(diào)用與其對(duì)等的主鍵調(diào)用類似。

              它使用的不是主鍵示例中的 dbp,而是使用 sdbp 根據(jù)次鍵來進(jìn)行查找:  

            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 中返回的內(nèi)容非常有趣。返回的是主數(shù)據(jù)庫中的數(shù)據(jù)即在數(shù)據(jù) DBT 中返回了同樣的東西,不管您是使用主鍵還是次鍵查找。

              但是,您會(huì)發(fā)現(xiàn)按次鍵查找時(shí),得到的結(jié)果與按主鍵檢索或 SQL 語句得到的結(jié)果有所不同。主鍵丟失,因?yàn)闆]有位置來返回它。所以,上面的代碼實(shí)際上實(shí)施  

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

              如果您需要主鍵,該如何做?答案是使用 dbp->pget dbc->pget 方法。這兩個(gè)方法與 get 方法一樣,只是它們專門設(shè)計(jì)用于您需要返回主鍵時(shí)的次索引查詢。因此,在這一情形中,結(jié)果中會(huì)包括主鍵、次鍵和數(shù)據(jù)元素:

            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"

              遍歷多個(gè)記錄

              到現(xiàn)在為止,我們僅返回了一個(gè)記錄。SQL 允許您返回多個(gè)記錄 (換言之,姓為 Mouse 的所有員工)。如何在 Berkeley DB 中實(shí)現(xiàn)此目的?

              讓我們考慮兩種情形。第一個(gè)情形,按照鍵來查找項(xiàng)目。第二個(gè)情形,搜索數(shù)據(jù)庫,按照不帶鍵的字段查找項(xiàng)目。

              假設(shè)您希望查找所有姓 Mouse 的員工(假設(shè)有多個(gè))。這意味著已經(jīng)創(chuàng)建了 last_name 次索引,從而允許重復(fù)。打開數(shù)據(jù)庫前,需要對(duì)它進(jìn)行配置以支持重復(fù):  

            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);

              現(xiàn)在,按次索引檢索時(shí),您可能想使用游標(biāo)來完成。開始時(shí)使用前面使用的代碼,可以添加一個(gè)循環(huán)以遍歷共享同一次鍵的項(xiàng)目: 

            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. */
              }

            通過使用游標(biāo)查找?guī)е付ㄦI的第一個(gè)項(xiàng)目,完成游標(biāo)的初始化,然后遍歷數(shù)據(jù)庫中帶同一鍵的所有項(xiàng)目。

              另一個(gè)可能的根據(jù)鍵進(jìn)行遍歷的形式為查詢形式,如

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

              再次使用游標(biāo)來遍歷,但這一次您想創(chuàng)建一個(gè)起始和結(jié)束點(diǎn)。Berkeley DB 使得起始點(diǎn)的建立非常簡單,結(jié)束點(diǎn)由應(yīng)用程序來完成。  

            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. */
              }

              要注意兩點(diǎn):1) DB_SET_RANGE 標(biāo)記作為循環(huán)的開始,這會(huì)將游標(biāo)定位于第一個(gè)大于或等于指定鍵的項(xiàng)目; 2) 應(yīng)用程序必須檢查循環(huán)內(nèi)范圍的終點(diǎn)。

             

            posted on 2011-08-28 18:33 肥仔 閱讀(594) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 數(shù)據(jù)庫

            AV狠狠色丁香婷婷综合久久| 亚洲人AV永久一区二区三区久久| 手机看片久久高清国产日韩| 午夜精品久久久久久影视777| 色老头网站久久网| 91久久香蕉国产熟女线看| 久久精品国产只有精品66 | 91精品久久久久久无码| 99精品国产在热久久无毒不卡 | 蜜臀久久99精品久久久久久小说| 久久精品免费一区二区三区| 久久久久青草线蕉综合超碰| 国产亚洲成人久久| 久久精品中文闷骚内射| 麻豆精品久久久久久久99蜜桃| 99久久中文字幕| 奇米影视7777久久精品人人爽| 成人国内精品久久久久一区| 国产精品中文久久久久久久| 亚洲国产二区三区久久| 日韩人妻无码一区二区三区久久| 精品久久久久久国产免费了| 俺来也俺去啦久久综合网| 亚洲欧美日韩精品久久亚洲区| 久久免费视频观看| 狠狠色综合久久久久尤物| 人妻无码αv中文字幕久久琪琪布| 久久久久无码专区亚洲av| 久久91精品久久91综合| 久久久久久综合网天天| 亚洲а∨天堂久久精品| 久久久无码精品午夜| 久久青青色综合| 亚洲精品视频久久久| 日韩欧美亚洲国产精品字幕久久久| 国内精品久久久久久不卡影院| 丁香五月网久久综合| 久久国产精品一区二区| 国产精品久久久久久久久鸭| 天天综合久久久网| 精品久久久久一区二区三区|