if ((ret = dbp->put(dbp, txn, &key, &data, 0)) != 0)
handle_error(ret);
</pre>
<p>Internally, a record with secondary key "Churchill" is inserted into
the secondary database (in addition to the insertion of "WC42" into the
primary, of course).</p>
<p>Deletes are similar. The SQL clause:</p>
<preclass="programlisting">DELETE FROM student WHERE (student_id = "WC42");</pre>
<p>looks like:</p>
<aid="prog_am15"></a>
<preclass="programlisting">DBT key;
memset(&key, 0, sizeof(DBT));
key.data = "WC42";
key.size = 4;
if ((ret = dbp->del(dbp, txn, &key, 0)) != 0)
handle_error(ret);</pre>
<p>Deletes can also be performed on the secondary index directly; a delete
done this way will delete the "real" record in the primary as well. If
the secondary supports duplicates and there are duplicate occurrences of
the secondary key, then all records with that secondary key are removed
from both the secondary index and the primary database. In
SQL:</p>
<preclass="programlisting">DELETE FROM lname WHERE (lastname = "Churchill ");</pre>
<p>In Berkeley DB:</p>
<aid="prog_am16"></a>
<preclass="programlisting">DBT skey;
memset(&skey, 0, sizeof(DBT));
skey.data = "Churchill ";
skey.size = 15;
if ((ret = sdbp->del(sdbp, txn, &skey, 0)) != 0)
handle_error(ret);</pre>
<p>Gets on a secondary automatically return the primary datum. If
<ahref="../api_reference/C/dbget.html"class="olink">DB->pget()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->pget()</a> is used in lieu of <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a>, the primary key is returned as well. Thus, the
equivalent of:</p>
<preclass="programlisting">SELECT * from lname WHERE (lastname = "Churchill ");</pre>
* Now pkey contains "WC42" and data contains Winston's record.
*/</pre>
<p>To create a secondary index to a Berkeley DB database, open the database that
is to become a secondary index normally, then pass it as the "secondary"
argument to the <ahref="../api_reference/C/dbassociate.html"class="olink">DB->associate()</a> method for some primary database.</p>
<p>After a <ahref="../api_reference/C/dbassociate.html"class="olink">DB->associate()</a> call is made, the secondary indexes become
alternate interfaces to the primary database. All updates to the
primary will be automatically reflected in each secondary index that has
been associated with it. All get operations using the <ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a>
or <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a> methods on the secondary index return the primary datum
associated with the specified (or otherwise current, in the case of
cursor operations) secondary key. The <ahref="../api_reference/C/dbget.html"class="olink">DB->pget()</a> and
<ahref="../api_reference/C/dbcget.html"class="olink">DBC->pget()</a> methods also become usable; these behave just like
<ahref="../api_reference/C/dbget.html"class="olink">DB->get()</a> and <ahref="../api_reference/C/dbcget.html"class="olink">DBC->get()</a>, but return the primary key in
addition to the primary datum, for those applications that need it as
well.</p>
<p>Cursor get operations on a secondary index perform as expected; although
the data returned will by default be those of the primary database, a
position in the secondary index is maintained normally, and records will
appear in the order determined by the secondary key and the comparison
function or other structure of the secondary database.</p>
<p>Delete operations on a secondary index delete the item from the primary
database and all relevant secondaries, including the current one.</p>
<p>Put operations of any kind are forbidden on secondary indexes, as there
is no way to specify a primary key for a newly put item. Instead, the
application should use the <ahref="../api_reference/C/dbput.html"class="olink">DB->put()</a> or <ahref="../api_reference/C/dbcput.html"class="olink">DBC->put()</a> methods
on the primary database.</p>
<p>Any number of secondary indexes may be associated with a given primary
database, up to limitations on available memory and the number of open
file descriptors.</p>
<p>Note that although Berkeley DB guarantees that updates made using any
<ahref="../api_reference/C/db.html"class="olink">DB</a> handle with an associated secondary will be reflected in the
that secondary, associating each primary handle with all the appropriate
secondaries is the responsibility of the application and is not enforced
by Berkeley DB. It is generally unsafe, but not forbidden by Berkeley DB, to modify
a database that has secondary indexes without having those indexes open
and associated. Similarly, it is generally unsafe, but not forbidden,
to modify a secondary index directly. Applications that violate these
rules face the possibility of outdated or incorrect results if the
secondary indexes are later used.</p>
<p>If a secondary index becomes outdated for any reason, it should be
discarded using the <ahref="../api_reference/C/dbremove.html"class="olink">DB->remove()</a> method and a new one created
using the <ahref="../api_reference/C/dbassociate.html"class="olink">DB->associate()</a> method. If a secondary index is no
longer needed, all of its handles should be closed using the
<ahref="../api_reference/C/dbclose.html"class="olink">DB->close()</a> method, and then the database should be removed using
a new database handle and the <ahref="../api_reference/C/dbremove.html"class="olink">DB->remove()</a> method.</p>
<p>Closing a primary database handle automatically dis-associates all
secondary database handles associated with it.</p>
<p>An error return during a secondary update in CDS or DS (which requires an abort in TDS) may leave a secondary index inconsistent in CDS or DS. There are a few non-error returns:
</p>
<divclass="itemizedlist">
<ultype="disc">
<li>0
</li>
<li>DB_BUFFER_SMALL
</li>
<li>DB_NOTFOUND
</li>
<li>DB_KEYEMPTY
</li>
<li>
DB_KEYEXIST
</li>
</ul>
</div>
<p>
In the case of any other error return during a secondary update in CDS or DS, delete the secondary indices, recreate them and set the <codeclass="literal">DB_CREATE flag</code> to the <codeclass="literal">DB->associate</code> method. Some examples of error returns that need to be handled this way are:</p>
<divclass="itemizedlist">
<ultype="disc">
<li>ENOMEM - indicating there is insufficient memory to return the requested item</li>
<li>EINVAL - indicating that an invalid flag value or parameter is specified</li>
</ul>
</div>
<p>Note that <codeclass="literal">DB_RUNRECOVERY</code> and <codeclass="literal">DB_PAGE_NOTFOUND</code> are fatal errors which should never occur during normal use of CDS or DS. If those errors are returned by Berkeley DB when running without transactions, check the database integrity with the <codeclass="literal">DB->verify</code> method before rebuilding the secondary indices. </p>