Tutorial: FoxPro E - Database Indexing & Searching

Dr. Thomas E. Hicks
Computer Science Department
Trinity University
 


  1. Client Database Structure/Layout
  2. List/Display Status
  3. Why Create Indexes?
  4. Creating A Simple Name Index -- Index On ??? Tag ???
  5. Set Order To
  6. Automatic Updating of Indexes
  7. ReIndex
  8. Unique Key Indexing - Seek
  9. Memory Variables
  10. String Functions & Manipulation
  11. Len
  12. Replace
  13. Duplicate Key Indexing
  14. Compound Indexing
  15. Possible Exam/Quiz Questions - FoxPro E

Client.DBF Structure/Layout
Create a folder called Client. Create a database table, called Client.dbf with the following layout. Modify Structure should open the Table Designer to create/modify the structure of  Client.DBF. (See Below)

Careful examination of the Table Designer above, will reveal that none of the fields have been selected as an index. Using the mouse,  select the Indexes Tab of the Table Designer. (See Below).

The Indexes tab also confirms that Clients.DBF has no indexes. Add the following contents to your Clients.DBF table.

When a database is not indexed, the records will be listed, browsed, and displayed in the order in which they were added to the database. In the browse window above, the records are in order from 1 to 7.  Note that the user, entering the data, (1) accidentally placed some blank spaces before Mouse, Minney, (2) accidentally entered Road Runner's state as entered Tn  instead of  TN, and (3) accidentally forgot to capitalize the first letters of rabbit, roger. 


List/Display Status


List Status <-- displays an environmental listing of the database that includes open tables, work areas, indexes, environmental settings, etc. (No Pause)  (See Below)

Display Status<-- displays an environmental listing of the database that includes open tables, work areas, indexes, environmental settings, etc. (Pause)

Processor is Pentium
Currently Selected Table:
Select area:  1, Table in Use:   C:\CLIENT\CLIENT.DBF    Alias:  CLIENT
                    Code page:   1252
                    Memo file:   C:\CLIENT\CLIENT.FPT
                      Lock(s):   Exclusive USE

File search path:
Default directory: C:\CLIENT
Print file/device:
Work area                       =    1
Margin                          =    0
Decimals                        =    2
Memowidth                       =   50
Typeahead                       =   20
Blocksize                       =   64
Reprocess                       =    0
Refresh                         = 0,5 SECONDS
DDE Timeout                     =    2000
DDE Safety                      = on

Code page:   1252
Collating sequence:  Machine
Compiler code page:   1252
Date format: American
Macro Hot Key =
UDF parameters are passed by:   VALUE
Textmerge Options
          Delimiters:  Left =  <<  Right =  >> Show

Alternate                    - off                      Fullpath                     - on
ANSI                         - off                      Heading                      - on
Asserts                      - off                      Help                         - on
Bell                         - off                      Intensity                    - on
Blink                        - on                       Lock                         - off
Brstatus                     - off                      Logerrors                    - on
Carry                        - off                      Mouse                        - on
Century                      - off                      Multilocks                   - off
Clear                        - on                       Near                         - on
Color                        - on                       Null                         - off
Compatible                   - off                      Optimize                     - on
Confirm                      - off                      Print                        - off
Console                      - on                       Readborder                   - off
Cursor                       - on                       Safety                       - on
Deleted                      - on                       Space                        - on
Device                       - scrn                     Status Bar                   - on
Echo                         - off                      Sysmenus                     - on
Escape                       - on                       Talk                         - on
Exact                        - off                      Textmerge                    - off
Exclusive                    - on                       Title                        - off
Fields                       - off                      Unique                       - off
Fixed                        - off

List status tells us much about the database environment. Observe the following:

  1. Only one table is open. It is open in work area 1. It is called C:\CLIENT\CLIENT.DBF
  2. If the Client.DBF table  had any indexes, they would be listed; we shall return to this later. This database table has no indexes.
  3. The memo file for the Client.DBF table is C:\CLIENT\CLIENT.FPT
  4. The Client.DBF table is not shared; it is opened for Exclusive USE
  5. The default directory is C:\CLIENT
  6. The bell will ring each time a field is filled or an alert occurs  - Bell - off
  7. The deleted records will not be displayed - Deleted - on
List Status To File Status NoConsole<-- sends the environmental listing of the database that includes open tables, work areas, indexes, environmental settings, etc. to a file called Status without displaying the results in the output window. (No Pause)

List Status To Printer<-- sends the environmental listing of the database that includes open tables, work areas, indexes, environmental settings, etc. to the printer and displays the results in the output window. (No Pause)

List Status To Printer NoConsole<-- sends the environmental listing of the database that includes open tables, work areas, indexes, environmental settings, etc. to the printer without displaying the results in the output window. (No Pause)
 


Why Create Indexes?
I. Make Searching For A Unique Key Extremely Efficient II. Order Output/Information III. Make Searching For A Common Key Extremely Efficient

Creating A Simple Name Index

Use Client                               <-- Open database Client.DBF
Index On Name Tag Name     <-- Create  Name Tag (based on Name Field ) within Client.CDX [Temporarily make Name the Master/Primary Index for the Client.DBF table.]

A database may have many indexes. An index can be created from a simple field, as illustrated above. An index can also be created from a combination of fields and/or variables; we will explore this later. All of the indexes for database XXXX.DBF will be stored in file XXXX.CDX. The index file has a .CDX extension and the same name as the corresponding database table (.DBF). The .CDX file will support hundreds of different indexes. Each index must have a unique Tag Name. Just as the field names should be descriptive of the field, the index Tag Name should be descriptive of the index. The index above was created from the Name Field and the index Tag Name is Name.

Browse Field RecNo = RecNo(), Name, Address, City, State, Zip, Phone, Age, Bald, Info <-- Browse

The Name Index is now the primary index in the Client.DBF; all output/information from List, Display All, Report Form, Label Form, Browse, and/or  Do Form will be in order by Name.

At first it might appear that the Names are out of order, but they are not. Character information is sorted in accordance with the ASCII (American Standard Code For Information Interchange) collating sequence.

The blanks at the beginning of "  Mouse, Minney" have a low ASCII value (32) thus forcing this record to the top. The lowercase r at the beginning of "rabbit, roger" has a high ASCII value of 114 thus forcing this record to the bottom. Things would have been much simpler had the user been more careful and consistent entering the data.

Blanks and case sensitivity are important when searching character data. Better indexes will be created at the end of this document.
Let us once more examine the  Table Designer of Client.DBF. From the Fields Tab we can see that there is an ascending index based on the Name field. (See Below)

From the Indexes Tab of the Table Designer, we can more carefully examine the Index. (See Below)

It is possible to create a new index with the Insert Button. It is possible to remove an existing index with the Delete button. Selecting the Expression ... button enables us to modify/examine the database index.  (See Below)

The screen above can be most helpful when creating/examining/altering complex indexes.

Processor is Pentium
Currently Selected Table:
Select area:  1, Table in Use:   C:\CLIENT\CLIENT.DBF    Alias:  CLIENT
                    Code page:   1252
          Structural CDX file:   C:\CLIENT\CLIENT.CDX
             Master Index tag:   NAME                             Machine                   Key:   NAME
                    Memo file:   C:\CLIENT\CLIENT.FPT
                      Lock(s): Exclusive USE
            Default directory: C:\CLIENT
Bell                         - off                   Deleted                      - on

List status tells us much about the database environment. Observe the following:

  1. Only one table is open. It is open in work area 1. It is called C:\CLIENT\CLIENT.DBF
  2. If the Client.DBF table  had any indexes, they would be listed; we shall return to this later. This database table has no indexes.
  3. The index file is called C:\CLIENT\CLIENT.FPT
  4. The master/primary index is optimized for searching. The NAME Tag is the master index.
  5. The NAME Tag index key was created from the NAME field.
  6. The memo file for the Client.DBF table is C:\CLIENT\CLIENT.FPT
  7. The Client.DBF table is not shared; it is opened for Exclusive USE
  8. The default directory is C:\CLIENT
  9. The bell will ring each time a field is filled or an alert occurs  - Bell - off

  10. The deleted records will not be displayed -
    Deleted - on
By default, all indexes will order information from smallest to largest (ascending order). Later in this document, you will learn to create an index that will order information from the largest to smallest (descending order).
 

Creating A Simple State Index

Use Client
<-- Open database Client.DBF
Index On State Tag State <-- Create  State Tag (based on State Field ) within Client.CDX [Temporarily make State the Master/Primary Index for the Client.DBF table.]

Browse Field RecNo = RecNo(), Name, Address, City, State, Zip, Phone, Age, Bald, Info <-- Browse

Once again  it might appear that the  States are out of order, but they are not. Remember that character information is sorted in accordance with the ASCII collating sequence. "TX" < "Tn"   [T (value 84) = T (value 84)  & X (value 88) <  n (value 110)]

The Client.DBF table now has two indexes. The first few lines of List Status may now be seen below. Observe the references to both indexes.

Processor is Pentium
Currently Selected Table:
Select area:  1, Table in Use:    C:\CLIENT\CLIENT.DBF    Alias:  CLIENT
                    Code page:    1252
          Structural CDX file:    C:\CLIENT\CLIENT.CDX
                    Index tag:    NAME                            Machine                   Key:    NAME
             Master Index tag:    STATE                           Machine                   Key:    STATE
                    Memo file:    C:\CLIENT\CLIENT.FPT
                      Lock(s):    Exclusive USE

 


Set Order To

Use Client
<-- Open database Client.DBF without a master/primary index.

Set Order To Name<-- Make the Name Tag the master/primary index.  All listings, displays, reports, browse, labels, etc. will be in order by Name.

Set Order To State<-- Make the State Tag the master/primary index.  All listings, displays, reports, browse, labels, etc. will be in order by State.
Use Client Order Name<-- Open database Client.DBF and make the Name Tag the master/primary index.

Use Client Order State <-- Open database Client.DBF and make the State Tag the master/primary index.

Only one index can be the master/primary search index at a time.
 


Automatic Updating of Indexes

All tag indexes are automatically updated with any and every

  1. Edit
  2. Change
  3. Delete
  4. Append
  5. Append Blank
  6. Pack
  7. Zap

ReIndex

ReIndex <-- regenerate all index files.

Should the index file, Client.IDX become corrupt, the ReIndex command can be used to regenerate all index files.


Unique Key Indexing - Seek

Use Client Order To Name
<-- Open database table  Client.DBF and make the Name Tag the master/primary index.  The read/write pointer will be placed at the logical top of the file. All listings, displays, reports, browse, labels, etc. will be in order

GoTo Top <-- Move the read/write pointer to the logical top of the database. Record # 3 (above)

GoTo Bottom <-- Move the read/write pointer to the logical top of the database. Record # 7 (above)

Set Near On <-- in the event that the search is unsuccessful, move the read/write pointer to the nearest record after where the sought item would be placed in the database table. (if possible) This environmental toggle may be observed in the status listing.

Seek "rabb" <-- move read/write pointer to record # 5 [Remember, the read/write pointer points to the current record.]
Seek "Run" <-- move read/write pointer to record # 2
Seek "M" <-- move read/write pointer to record # 6
Seek "Mouse, Mic" <-- move read/write pointer to record # 1
Seek "Woman, Wonder" <-- move read/write pointer to record # 7
Seek "F" <-- move read/write pointer to record # 6 [ not found - record after where "F" would be placed]
Seek "Mouse, Min" move read/write pointer to record # 2 [ not found because of leading blanks - record after where "Mouse, Min" would be placed]
Seek "Duck, Huey"<-- move read/write pointer to record # 6 [ not found - record after where "Duck, Huey" would be placed]
Seek "Clinton, Bill"<-- move read/write pointer to record # 3 [ not found - record after where "Clinton, Bill" would be placed]
Seek "Duck, Huey"<-- move read/write pointer to record # 6 [ not found - record after where "Duck, Huey" would be placed]
Seek "xRay, Man" <-- move read/write pointer to EOF [ not found - record after where "xRay, Man" would be placed]

Seek "mouse, mickey"  <-- move read/write pointer to 5 [ because it is case sensitive, this search is unsuccessful - record after where "mouse, mickey" would be placed]. Character information is sorted in accordance with the ASCII (American Standard Code For Information Interchange) collating sequence.

Blanks and case sensitivity are important when searching character data. Better indexes can be created!
 


Memory Variables

FirstName = "Tom"  <-- creates a character  memory variable whose symbolic name shall be  FirstName (if it does not already exit and assigns the string "Tom" to that variable.

LastName = 'Hicks'  <-- creates a character memory variable whose symbolic name shall be  LastName (if it does not already exit and assigns the string "Hicks" to that variable.

NoName = "  joHN dOe  " <-- creates a character memory variable whose symbolic name shall be  NoName (if it does not already exit and assigns the string "  joHN dOe " to that variable.  Leading and trailing blanks and case are significant.

Display Memory  <-- displays local variables, FoxPro system variables, window definitions, menu definitions, and pop-up window definitions.  The default number of user variables that may exit at any one time is 1024; this may be increased to as many as 65,000. (Only the local variables are displayed below).
 

Clear Memory  <-- clears all  local variables, FoxPro system variables, window definitions, menu definitions, and pop-up window definitions.

? FirstName  <-- displays memory variable FirstName - displays  Tom
? LastName  <-- displays memory variable LastName - displays Hicks
? "Hello"  <-- displays character string  - displays Hello

? M.FirstName  <-- displays memory variable FirstName - displays  Tom
? M.LastName  <-- displays memory variable LastName - displays Hicks

NotName = FirstName <-- creates a character  memory variable whose symbolic name shall be  NoName (if it does not already exit and assigns the contents to the contents of variable FirstName.

Key = 5  <-- creates a numeric  memory variable whose symbolic name shall be Key  (if it does not already exit and assigns 5 to that variable.

Key = 5.5  <-- creates a numeric  memory variable whose symbolic name shall be Key  (if it does not already exit and assigns 5.5 to that variable.

Valid = .T. <-- creates a logical memory variable whose symbolic name shall be Valid (if it does not already exit and assigns True to that variable.

Valid = Not .F. <-- creates a logical memory variable whose symbolic name shall be Valid (if it does not already exit and assigns True to that variable.

Christmas = {12/25/98} <-- creates a logical memory variable whose symbolic name shall be Christmas (if it does not already exit and assigns 12/25/98  to that variable.
 


String Functions & Manipulation

FirstName = "Tom"

LastName = 'Hicks'
NoName = " joHN  dOe   "
The + symbol is used to concatenate (merge/combine) two or more strings

? "Hello" + FirstName  <-- displays HelloTom
? "Hello " + FirstName  <-- displays Hello Tom
? FirstName + LastName  <-- displays TomHicks
? FirstName + ' ' + LastName  <-- displays Tom Hicks
? LastName + ', ' + FirstName  <-- displays Hicks, Tom

The Upper(var)  function explicitly returns the upper case (all capitals) version of the passed string argument.

? '[' + Upper(FirstName)+ ']'  <-- displays [TOM]
? '[' + Upper(LastName )+ ']'   <-- displays [HICKS]
? '[' + Upper("gOoD TiMes")+ ']'   <-- displays [GOOD TIMES]
? '[' + Upper(NoName)+ ']'   <-- displays [ JOHN  DOE   ]

TotalName = LastName + ', ' + FirstName   <-- creates a local memory variable whose symbolic name shall be  TotalName (if it does not already exit and assigns the contents to Hicks, Tom

TotalName = Upper(LastName) + ', ' + Upper(FirstName)  <-- creates a local memory variable whose symbolic name shall be  TotalName (if it does not already exit and assigns the contents to Hicks, Tom

The Lower(var)  function explicitly returns the lower case (all non-capitals) version of the passed string argument.

? '[' + Lower(FirstName)+ ']'  <-- displays [tom]
? '[' + Lower(LastName ) + ']'   <-- displays [hicks]
? '[' + Lower("gOoD TiMes") + ']'   <-- displays [good times]
? '[' + Lower(NoName)+ ']'   <-- displays [ john  doe   ]

The Proper(var)  function explicitly returns the proper case (all first letters capitals) version of the passed string argument.

? '[' + Proper(FirstName)+ ']'  <-- displays [Tom]
? '[' + Proper(LastName ) + ']'   <-- displays [Hicks]
? '[' + Proper("gOoD TiMes") + ']'   <-- displays [Good Times]
? '[' + Proper(NoName)+ ']'   <-- displays [ John  Doe   ]

The LTrim(var)  function explicitly returns the passed string argument without any leading blanks (trim the left side of string)

NoName = "      joHN  dOe   "
? '[' + LTrim("   Tom   ")+ ']'  <-- displays [Tom   ]
? '[' + LTrim("   Hicks   ") + ']'   <-- displays [Hicks   ]
? '[' + LTrim(NoName)+ ']'   <-- displays [joHN  dOe   ]
? '[' + Proper(LTrim(NoName))+ ']'   <-- displays [John  Doe   ]

The RTrim(var)  function explicitly returns the passed string argument without any trailing  blanks (trim the right side of string)

NoName = "      joHN  dOe   "
? '[' + RTrim("   Tom   ")+ ']'  <-- displays [   Tom]
? '[' + RTrim("   Hicks   ") + ']'   <-- displays [   Hicks]
? '[' + RTrim(NoName)+ ']'   <-- displays [  joHN  dOe]
? '[' + Proper(RTrim(NoName))+ ']'   <-- displays [John  Doe   ]

The AllTrim(var)  function explicitly returns the passed string argument without any trailing  blanks (trim the right side of string)

NoName = "      joHN  dOe   "
? '[' + AllTrim("   Tom   ")+ ']'  <-- displays [Tom]
? '[' + AllTrim("   Hicks   ") + ']'   <-- displays [Hicks]
? '[' + AllTrim(NoName)+ ']'   <-- displays [joHN  dOe]
? '[' + AllTrim(Proper(NoName))+ ']'   <-- displays [John  Doe]
? '[' + AllTrim('        John        Doe     ") + ']'   <-- displays [John      Doe]
? '[' + AllTrim(Upper("   hICkS   ")) +','+ AllTrim(Upper("   tOm   ")) + ']'   <-- displays [Hicks, Tom]
 


Replace

Replace Name With  "Hicks, Tom"   <-- replaces database field Name with "Hicks, Tom" in only the current record. If the Name field were only 8 characters in size, it would use the first 8 characters of the string  "Hicks, Tom" [Name would contain Hicks, T]  If the Name field were only 20 characters in size, it would place blanks in the remaining characters at the end.

Replace All Name With  " "   <-- replaces all of the database Name fields  with blank space.

Replace All Name With Upper(Name)   <-- replaces all of the database Name fields with their upper case equivalents.
Replace All Name With Lower(Name)   <-- replaces all of the database Name fields with their lower case equivalents.
Replace All Name With Proper(Name)   <-- replaces all of the database Name fields with their proper case equivalents.

Replace All Name With Upper(LTrim(Name))   <-- replaces all of the database Name fields with their upper case equivalents minus any leading blanks.
Replace All Name With Upper(LTrim(Name))   <-- replaces all of the database Name fields with their lower case equivalents minus any leading blanks.
Replace All Name With Upper(LTrim(Name))   <-- replaces all of the database Name fields with their proper case equivalents minus any leading blanks.
 


Len

Use Clint Order To Name<-- Open database table  Client.DBF and make the Name Tag the master/primary index.  The read/write pointer will be placed at the logical top of the file. All listings, displays, reports, browse, labels, etc. will be in order. (See Above)

FirstName = "Tom"
LastName = 'Hicks'
Name = LastName + ', ' + FirstName

? Len(FirstName) <-- display the length of character field FirstName. Since a three character field was created and filled with "Tom" in the assignment statement above, a 3 is displayed.

? Len(LastName) <-- display the length of character field FirstName. Since a five character field was created and filled with "Hicks" in the assignment statement above, a 5 is displayed.

? Len('Tom Hicks') <-- display the length of character string; blanks count as characters.  A  9 is displayed.

? Len(State) <-- display the size of the character  State field.  A  2 is displayed.
? Len(Zip) <-- display the size of the character Zip field.  A  5 is displayed.  In the event that a 3 digit zip code  (123) were entered into the current record, a 5 would be displayed because the remainder of the field would be blank filled.

? Len(Age) <-- Not Valid - not a character field.

GoTo Top <-- move the read/write pointer to the logical top of the database table - Record # 3

? Name   <-- displays Name Duck, Donald from the open database table.
? Client.Name   <-- displays Name Duck, Donald from the open Clients.DBF database table. [ Uses a database modifier]
? M.Name   <-- displays memory variable Name Hicks, Tom from the database table. [ Uses a memory variable  modifier]

When a database field has the same name as a memory variable, the database field has priority. It is often necessary to use the M. modifier to specifically identify a memory variable. When two database tables that have the same field name are both open, it will be necessary to use the database modifier - Client.Name vs. Employee.Name.

 


Duplicate Key Indexing

Use Client Order State <-- open database table Client.DBF  with State as the master/primary index. The read/write pointer is at the logical top : record 6

Set Near On <-- in the event that the search is unsuccessful, move the read/write pointer to the nearest record after where the sought item would be placed in the database table. (if possible) This environmental toggle may be observed in the status listing.

Seek "TX" <-- move read/write pointer to record # 1
Seek "OK" <-- move read/write  pointer to record # 1
Seek "A" <-- move read/write pointer to record # 6
Seek "Z" <-- move read/write pointer to End of File (EOF)

Seek "fl"  <-- move read/write pointer to EOF [ because it is case sensitive, this search is unsuccessful - record after where "fl" would be placed]. Character information is sorted in accordance with the ASCII (American Standard Code For Information Interchange) collating sequence.



The State index is of little value for searching; the seek only moves the read/write pointer to the first match. When the State index is the master, it is quite beneficial for any type of queries like the following:

    List For State = "TX"
    Report Form PhoneList For State = "TX"
    Label Form Mail For State = "TX"
    Display All For State = "TX"
    Set Filter To State = "TX"



Without the State index, each of the queries above would require examination of the entire database. Suppose the Client.DBF table had 100,000 records and that  2,000 of these were  TX records. Without a State index, each of the queries above
  1. move the read/write pointer to the top of the database table
  2. read the current record into memory
  3. decide if the current record matches the search condition State field of the current record = "TX"
  4. process that record if there is a match
  5. if not at the bottom of the file then skip to the next record and repeat steps 2-5
These queries require all 100,000 Client.DBF records to be examined.


State is now the master/primary index. At least part of the State index resides in RAM when the database is opened; our database table with 100,000 records might split this index into several parts. It is beyond the scope of this document to discuss exactly how the indexes are designed and accessed. For the sake of discussion, let us concede that the indexes containing the 2,000 TX records might require as many as 1 or 2 disk accesses to load all of the indexes into memory. With a State index, each of the queries above

  1. efficiently search the internal memory index for the first index = "TX"
  2. read that record and process it
  3. if the next key is also a match repeat steps 1-2
These queries require all 20,000 Client.DBF records to be examined and possible 1 or 2 Client.CDX records. As you might expect, this would be almost 50 times faster than processing the queries without an index. If a query by state is only to be done one time, it is certainly not worth while to create an index. If a query by state is going to be done occasionally, a state index should be created.
 


Quality Indexing

Suppose we were to have created the Name Tag with the following:

Index On AllTrim(Upper(Name)) Tag Name       <-- Create  Name Tag (based on Name Field ) within Client.CDX.  In producing the index keys, all leading and trailing blanks will be removed from the Name field and all characters will be converted to upper case capitals.

Browse Field RecNo = RecNo(), Name, Address, City, State, Zip, Phone, Age, Bald, Info <-- Browse would then produce

This new Name index will correct data entry errors that accidentally insert blank spaces at the beginning or end of a the name field. This index will correct data entry errors made by accidentally selecting the wrong case in the name field. As we shall see in FoxProE, this index will make searching by the user more successful. Unfortunately, it does not correct problems that occur when a user enters multiple spaces between the first and last name.

Seek "RABB" <-- move read/write pointer to record # 5
Seek "M" <-- move read/write pointer to record # 6
Seek "MOUSE, MIN" move read/write pointer to record # 4
Seek "MOUSE, MIC" <-- move read/write pointer to record # 1
Seek "WOMAN, WONDER" <-- move read/write pointer to record # 7
Seek "F" <-- move read/write pointer to record # 6 [ not found - record after where "F" would be placed]
Seek "CLINTON, BILL"<-- move read/write pointer to record # 3 [ not found - record after where "Clinton, Bill" would be placed]
Seek "DUCK, HUEY"<-- move read/write pointer to record # 6 [ not found - record after where "Duck, Huey" would be placed]
Seek "Z" <-- move read/write pointer to the EOF().

Index On AllTrim(Upper(State)) Tag State       <-- Create  State Tag (based on State Field ) within Client.CDX.  In producing the index keys, all leading and trailing blanks will be removed from the State field and all characters will be converted to upper case capitals. This would be a better State index.

Let us return to the Indexes Tab of  Table Designer for the Client.DBF after entering the alternative indexes from this section. (See Below)

Selecting the expression ... button enables us to modify/examine the name index.  (See Below)

Selecting the expression ... button enables us to modify/examine the state index.  (See Below)


 


Compound Indexing

Let us create some good indexes for database Employee.DBF above. Note that the separation of the first name and the last name above is more likely to standardize the user input; it is now impossible for the user to enter multiple blanks between the last and first name; it is impossible for the user to forget the semicolon.

Index On AllTrim(Upper(FirstName)) Tag FirstName
Index On AllTrim(Upper(LastName)) Tag LastName

The index pair above is poor. We can have only one master index. If the LastName were the master index, then all of the Smith's would be together, but (1) it would not be possible to use the seek command to find Smith, John as opposed to Smith, Michael (2) it would not be possible to get labels, reports, or screens to properly sort the employees by their full name. The compound  index below demonstrates how multiple fields can be used to comprise an index.

Index On AllTrim(Upper(LastName)) + ', ' + AllTrim(Upper(FirstName)) Tag LastName <-- builds the index, called Name,  from the lastname and the firstname fields.

Index On EmployNo Tag No <-- builds the index, called No,  from the EmployNo field. Since numeric data can not have leading blanks, there is no need to trim the index. Since numeric data can not have character data , there is no need to upper  the index. The people will be in order from the largest employee number to the smallest.

Index On EmployNo Tag No Ascending <-- builds the index, called No,  from the EmployNo field. Since numeric data can not have leading blanks, there is no need to trim the index. Since numeric data can not have character data , there is no need to upper  the index. The people will be in order from the smallest employee number to the largest.

Index On EmployNo Tag No Descending <-- builds the index, called No,  from the EmployNo field. Since numeric data can not have leading blanks, there is no need to trim the index. Since numeric data can not have character data , there is no need to upper  the index. The people will be in order from the smallest employee number to the largest.

Index On BirthDate Tag BirthDate <-- builds the index, called BirthDate,  from the BirthDate field. Since date data can not have leading blanks, there is no need to trim the index. Since date data can not have character data , there is no need to upper  the index. The people will be in order from youngest to oldest.


Possible Exam/Quiz Questions - FoxPro E

May be accessed through URL: http://www.cs.trinity.edu/~thicks
May also be accessed through URL: http://carme.cs.trinity.edu
This Document May Not Be Printed or Reproduced Without Written Permission.
 2003 Copyright : Dr. Thomas E. Hicks
Permission granted : Professional Educators & College Students may print one copy of this page!

Dr. Thomas E. Hicks

Computer Science Department    
Trinity University

"Dr. Web"