375 lines
14 KiB
HTML
375 lines
14 KiB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||
<title>Reading and Writing Database Records</title>
|
||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
|
||
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
|
||
<link rel="up" href="DBEntry.html" title="Chapter 3. Database Records" />
|
||
<link rel="previous" href="DBEntry.html" title="Chapter 3. Database Records" />
|
||
<link rel="next" href="DbCXXUsage.html" title="Database Usage Example" />
|
||
</head>
|
||
<body>
|
||
<div class="navheader">
|
||
<table width="100%" summary="Navigation header">
|
||
<tr>
|
||
<th colspan="3" align="center">Reading and Writing Database Records</th>
|
||
</tr>
|
||
<tr>
|
||
<td width="20%" align="left"><a accesskey="p" href="DBEntry.html">Prev</a> </td>
|
||
<th width="60%" align="center">Chapter 3. Database Records</th>
|
||
<td width="20%" align="right"> <a accesskey="n" href="DbCXXUsage.html">Next</a></td>
|
||
</tr>
|
||
</table>
|
||
<hr />
|
||
</div>
|
||
<div class="sect1" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h2 class="title" style="clear: both"><a id="usingDbt"></a>Reading and Writing Database Records</h2>
|
||
</div>
|
||
</div>
|
||
<div></div>
|
||
</div>
|
||
<p>
|
||
When reading and writing database records, be aware that there are some
|
||
slight differences in behavior depending on whether your database supports duplicate
|
||
records. Two or more database records are considered to be duplicates of
|
||
one another if they share the same key. The collection of records
|
||
sharing the same key are called a <span class="emphasis"><em>duplicates set.</em></span>
|
||
|
||
<span>
|
||
In DB, a given key is stored only once for a single duplicates set.
|
||
</span>
|
||
</p>
|
||
<p>
|
||
By default, DB databases do
|
||
not support duplicate records. Where duplicate records are supported,
|
||
cursors (see below) are <span>typically</span> used
|
||
to access all of the records in the duplicates set.
|
||
</p>
|
||
<p>
|
||
DB provides two basic mechanisms for the storage and retrieval of database
|
||
key/data pairs:
|
||
</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p>
|
||
The
|
||
|
||
|
||
<tt class="methodname">Db::put()</tt>
|
||
and
|
||
|
||
|
||
<tt class="methodname">Db::get()</tt>
|
||
methods provide the easiest access for all non-duplicate records in the database.
|
||
These methods are described in this section.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>Cursors provide several methods for putting and getting database
|
||
records. Cursors and their database access methods are described in
|
||
<a href="Cursors.html">Using Cursors</a>.</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="databaseWrite"></a>Writing Records to the Database</h3>
|
||
</div>
|
||
</div>
|
||
<div></div>
|
||
</div>
|
||
<p>
|
||
Records are stored in the database using whatever organization is
|
||
required by the access method that you have selected. In some cases (such as
|
||
BTree), records are stored in a sort order that you may want to define
|
||
(see <a href="btree.html#comparators">Setting Comparison Functions</a> for more information).
|
||
</p>
|
||
<p>
|
||
In any case, the mechanics of putting and getting database records do not
|
||
change once you have selected your access method, configured your
|
||
sorting routines (if any), and opened your database. From your
|
||
code's perspective, a simple database put and get is largely the
|
||
same no matter what access method you are using.
|
||
</p>
|
||
<p>
|
||
You use
|
||
|
||
<tt class="methodname">Db::put()</tt>
|
||
to put, or write, a database record. This method requires you to provide
|
||
the record's key and data in the form of a pair of
|
||
|
||
<span><tt class="methodname">Dbt</tt> objects.</span>
|
||
You can also provide one or more flags that control DB's behavior
|
||
for the database write.
|
||
</p>
|
||
<p>
|
||
Of the flags available to this method, <tt class="literal">DB_NOOVERWRITE</tt>
|
||
may be interesting to you. This flag disallows overwriting (replacing)
|
||
an existing record in the database. If the provided key already exists
|
||
in the database, then this method returns <tt class="literal">DB_KEYEXIST</tt> even if
|
||
the database supports duplicates.
|
||
</p>
|
||
<p>
|
||
For example:
|
||
</p>
|
||
<a id="cxx_dbt3"></a>
|
||
<pre class="programlisting">#include <db_cxx.h>
|
||
#include <string.h>
|
||
|
||
...
|
||
|
||
char *description = "Grocery bill.";
|
||
float money = 122.45;
|
||
|
||
Db my_database(NULL, 0);
|
||
// Database open omitted for clarity
|
||
|
||
Dbt key(&money, sizeof(float));
|
||
Dbt data(description, strlen(description) + 1);
|
||
|
||
int ret = my_database.put(NULL, &key, &data, DB_NOOVERWRITE);
|
||
if (ret == DB_KEYEXIST) {
|
||
my_database.err(ret, "Put failed because key %f already exists", money);
|
||
}</pre>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="CoreDatabaseRead"></a>Getting Records from the Database</h3>
|
||
</div>
|
||
</div>
|
||
<div></div>
|
||
</div>
|
||
<p>
|
||
You can use the
|
||
|
||
<tt class="methodname">Db::get()</tt>
|
||
method to retrieve database records. Note that if your
|
||
database supports duplicate records, then by default this method will only
|
||
return the first record in a duplicate set. For this reason, if your
|
||
database supports duplicates, the common solution is to use a cursor to retrieve
|
||
records from it. Cursors are described in <a href="Cursors.html">Using Cursors</a>.
|
||
</p>
|
||
<p>
|
||
(You can also retrieve a set of duplicate records using a bulk get.
|
||
To do this, you use the <tt class="literal">DB_MULTIPLE</tt> flag on the
|
||
call to
|
||
|
||
<span><tt class="methodname">Db::get()</tt>.</span>
|
||
|
||
For more information, see the DB Programmer's Reference Guide).
|
||
</p>
|
||
<p>
|
||
By default,
|
||
|
||
<tt class="methodname">Db::get()</tt>
|
||
returns the first record found whose key matches the key
|
||
provide on the call to this method. If your database supports
|
||
duplicate records, you can change this behavior slightly by supplying
|
||
the <tt class="literal">DB_GET_BOTH</tt> flag. This flag causes
|
||
|
||
<tt class="methodname">DB::get()</tt>
|
||
to return the first record that matches the provided key and data.
|
||
</p>
|
||
<p>
|
||
If the specified key and/or data does not exist in the database, this
|
||
method returns <tt class="literal">DB_NOTFOUND</tt>.
|
||
</p>
|
||
<a id="cxx_dbt4"></a>
|
||
<pre class="programlisting">#include <db_cxx.h>
|
||
#include <string.h>
|
||
|
||
...
|
||
|
||
float money;
|
||
char description[DESCRIPTION_SIZE + 1];
|
||
|
||
Db my_database(NULL, 0);
|
||
// Database open omitted for clarity
|
||
|
||
money = 122.45;
|
||
|
||
Dbt key, data;
|
||
|
||
key.set_data(&money);
|
||
key.set_size(sizeof(float));
|
||
|
||
data.set_data(description);
|
||
data.set_ulen(DESCRIPTION_SIZE + 1);
|
||
data.set_flags(DB_DBT_USERMEM);
|
||
|
||
my_database.get(NULL, &key, &data, 0);
|
||
|
||
// Description is set into the memory that we supplied. </pre>
|
||
<p>
|
||
Note that in this example, the
|
||
<tt class="literal">data.size</tt>
|
||
field would be automatically set to the size of the retrieved data.
|
||
</p>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="recordDelete"></a>Deleting Records</h3>
|
||
</div>
|
||
</div>
|
||
<div></div>
|
||
</div>
|
||
<p>
|
||
|
||
You can use the
|
||
|
||
|
||
<tt class="methodname">Db::del()</tt>
|
||
method to delete a record from the database. If your database supports
|
||
duplicate records, then all records associated with the provided key are
|
||
deleted. To delete just one record from a list of duplicates, use a
|
||
cursor. Cursors are described in <a href="Cursors.html">Using Cursors</a>.
|
||
|
||
</p>
|
||
<p>
|
||
You can also delete every record in the database by using
|
||
|
||
|
||
<tt class="methodname">Db::truncate().</tt>
|
||
</p>
|
||
<p>For example:</p>
|
||
<a id="cxx_dbt5"></a>
|
||
<pre class="programlisting">#include <db_cxx.h>
|
||
|
||
...
|
||
|
||
Db my_database(NULL, 0);
|
||
// Database open omitted for clarity
|
||
|
||
float money = 122.45;
|
||
Dbt key(&money, sizeof(float));
|
||
|
||
my_database.del(NULL, &key, 0);</pre>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="datapersist"></a>Data Persistence</h3>
|
||
</div>
|
||
</div>
|
||
<div></div>
|
||
</div>
|
||
<p>
|
||
When you perform a database modification, your modification is made
|
||
in the in-memory cache. This means that your data modifications
|
||
are not necessarily flushed to disk, and so your data may not appear
|
||
in the database after an application restart.
|
||
</p>
|
||
<p>
|
||
Note that as a normal part of closing a database, its cache is
|
||
written to disk. However, in the event of an application or system
|
||
failure, there is no guarantee that your databases will close
|
||
cleanly. In this event, it is possible for you to lose data. Under
|
||
extremely rare circumstances, it is also possible for you to
|
||
experience database corruption.
|
||
</p>
|
||
<p>
|
||
Therefore, if you care if your data is durable across system
|
||
failures, and to guard against the rare possibility of
|
||
database corruption, you should use transactions to protect your
|
||
database modifications. Every time you commit a transaction, DB
|
||
ensures that the data will not be lost due to application or
|
||
system failure. Transaction usage is described in the
|
||
|
||
|
||
|
||
|
||
<span>
|
||
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide.
|
||
</span>
|
||
</p>
|
||
<p>
|
||
If you do not want to use transactions, then the assumption is that
|
||
your data is of a nature that it need not exist the next time your
|
||
application starts. You may want this if, for example, you are using
|
||
DB to cache data relevant only to the current application
|
||
runtime.
|
||
</p>
|
||
<p>
|
||
If, however, you are not using transactions for some reason and you
|
||
still want some guarantee that your database modifications are
|
||
persistent, then you should periodically
|
||
|
||
|
||
<span>call <tt class="methodname">Db::sync()</tt>.</span>
|
||
Syncs cause any dirty entries in the in-memory cache and the
|
||
operating system's file cache to be written to disk. As
|
||
such, they are quite expensive and you should use them sparingly.
|
||
</p>
|
||
<p>
|
||
Remember that by default a sync is performed any time a non-transactional
|
||
database is closed cleanly. (You can override this behavior by
|
||
specifying
|
||
<tt class="literal">DB_NOSYNC</tt>
|
||
|
||
on the call to
|
||
|
||
<span><tt class="methodname">Db::close()</tt>.)</span>
|
||
|
||
|
||
That said, you can manually run a sync by calling
|
||
|
||
|
||
<tt class="methodname">Db::sync().</tt>
|
||
|
||
|
||
</p>
|
||
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
|
||
<h3 class="title">Note</h3>
|
||
<p>
|
||
If your application or system crashes and you are not using
|
||
transactions, then you should either discard and recreate your
|
||
databases, or verify them. You can verify a database using
|
||
|
||
<span>Db::verify().</span>
|
||
|
||
If your databases do not verify cleanly, use the
|
||
<span><b class="command">db_dump</b></span> command to salvage as much of the
|
||
database as is possible. Use either the <tt class="literal">-R</tt> or
|
||
<tt class="literal">-r</tt> command line options to control how
|
||
aggressive <span><b class="command">db_dump</b></span> should be when salvaging
|
||
your databases.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="navfooter">
|
||
<hr />
|
||
<table width="100%" summary="Navigation footer">
|
||
<tr>
|
||
<td width="40%" align="left"><a accesskey="p" href="DBEntry.html">Prev</a> </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="u" href="DBEntry.html">Up</a>
|
||
</td>
|
||
<td width="40%" align="right"> <a accesskey="n" href="DbCXXUsage.html">Next</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="40%" align="left" valign="top">Chapter 3. Database Records </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="h" href="index.html">Home</a>
|
||
</td>
|
||
<td width="40%" align="right" valign="top"> Database Usage Example</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>
|