needed then it is called a covering index. Note that columns defined in the table primary index are also found in secondary indexes and can be similarly retrieved using JET_bitRetrieveFromPrimaryBookmark. Index keys are stored in normalized form which can be, in many cases, denormalized to the original column value. Normalization is not always reversible. For example, Text and Long Text column types cannot be denormalized. In addition, index keys may be truncated when column data is very long. In cases where columns cannot be retrieved directly from secondary indexes, the record can always be accessed to retrieve the necessary data. Index intersection Queries often involve a combination of restrictions on data. An efficient means of processing a restriction is to use an available index. However, if a query involves multiple restrictions then applications often process the restrictions by walking the full index range of the most restrictive predicate satisfied by a single index. Any remaining predicate, called the residual predicate, is processed by applying the predicate to the record itself. This is a simple method but has the disadvantage of potentially having to perform many disk accesses to bring records into memory to apply the residual predicate. Index intersection is an important query mechanism in which multiple indexes are used together to more efficiently process a complex restriction. Instead using only a single index, index ranges on multiple indexes are combined to result in a much smaller number of records on which any residual predicate can be applied. ESE makes this easy by supplying an IntersectIndexes operation. This operation accepts a series of index ranges on indexes from the same table and returns a temporary table of primary keys that can be used to navigate to the base table records that satisfy all index predicates. Pre-joined tables A join is a common operation on a normalized table design, where logically related data is brought back together for use in an application. Joins can be expensive operations because many data accesses may be needed to bring related data into memory. This effort can be optimized in some cases by defining a single base table that contains data for two or more logical tables. The column set of the base table is the union of the column sets of these logical tables. Tagged columns make this possible because of their good handling of both multi-valued and sparse valued data. Since related data