Delete, Deleted(), Pack, Recall, Set Deleted, Set("Deleted")
These commands and functions control deletion of records from a table. Deleting a record in FoxPro (and in any other Xbase language) is a dance—a two-step—because it takes two steps to really and truly make a record go away. First, you "mark" the record for deletion. You can permanently throw away all the marked records when you want. Until you do so, you can "unmark" the record. It's like deleting files using the Windows Recycle Bin; the file's not really deleted from the disk until you empty the bin. Come to think of it, it's not so different from real life. You put something in the trash, but you can retrieve it (and uncrumple it) until the trash can is emptied.The first byte of every record in each table is a deletion flag. That's why the total length shown in the Table Designer is always at least one more than the sum of the field lengths (null fields can further increase the record length; see "Nulls" in "DBF, FPT, CDX, DBC—Hike!") This flag field contains an asterisk ("*") when the record is marked for deletion and a space when it's not marked. You can see this by opening up a table using a hex editor—that's how we figured it out.
Usage |
DELETE [ Scope ] [ FOR lForExpression ] [ WHILE lWhileExpression ] [ IN cAlias | nWorkArea ] [ NOOPTIMIZE ] RECALL [ Scope ] [ FOR lForExpression ] [ WHILE lWhileExpression ] [ IN cAlias | nWorkArea ] [ NOOPTIMIZE ] |
Example |
* This might be in the Click event of a Delete button #INCLUDE FoxPro.H IF MESSAGEBOX("Do you really want to delete this record",; MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2, ; "Delete current record?") = ID_YES DELETE NEXT 1 ENDIF |
Usage |
PACK [ MEMO | DBF ] [ TableName ] [ IN cAlias | nWorkArea ] |
Parameter |
Value |
Meaning |
TableName |
Name |
In VFP 7, specifies the table to pack without opening it first. Just add the path and file name of the table to the command. |
cAlias |
Character |
Pack the table that's open with the specified alias. |
Omitted |
If nWorkArea and TableName are also omitted, pack the table that's open in the current work area. |
|
nWorkArea |
Numeric |
Pack the table that's open in the specified work area. |
Omitted |
If cAlias and TableName are also omitted, pack the table that's open in the current work area. |
USE MyTable ORDER BestOrder EXCLUSIVE COPY TO MyNewTable FOR NOT DELETED() IF FILE("MyNewTable.DBF") AND FILE("MyNewTable.FPT") * Only go on if the new version was created USE DELETE FILE MyTable.DBF DELETE FILE MyTable.FPT DELETE FILE MyTable.CDX RENAME MyNewTable.DBF TO MyTable.DBF RENAME MyNewTable.FPT TO MyTable.FPT * Now re-create the indexes ELSE WAIT WINDOW "Trouble in Paradise" NOWAIT ENDIFFor tables in a database, things are a little more difficult. Using the COPY TO approach, you lose all the database information for the table. In particular, your relations get trashed. Your best bet is to get a good database maintenance tool (like Stonefield Database Toolkit) to handle these chores.Memo files (FPT) can accumulate a lot of wasted space because replacement of existing data doesn't reuse the same disk space. Over time, this can really add up, especially if those humongous general field OLE objects are used and edited. PACK MEMO cleans up this wasted space without removing the records marked for deletion. There's also a PACK DBF version, but it's another of those items that seems to have been added for completeness, not because it was useful. It removes deleted records without compacting memo space. (If you find a reason to use it, let us know.)VFP 7 makes it a little easier to use PACK. First, it acquires an IN clause, so you can specify which table you mean and not depend on being in the right work area. More interestingly, the new TableName parameter means that you can pack a table without having to explicitly open it first. To use it, the table must not be open anywhere, since PACK needs exclusive access. Among other things, this means that you can't combine the TableName and IN clauses, because having the table open in a work area prevents it from being opened exclusively for packing. Like a good citizen, VFP cleans up after itself and the table is closed after it's packed. Would that all our code was as careful.
Usage |
lIsDeleted = DELETED( [ cAlias | nWorkArea ] ) |
BROWSE FOR NOT DELETED()to see all the current records in a table.
Usage |
SET DELETED ON | OFF cDeletedSetting = SET("DELETED") |
Example |
cOldDeleted=SET("DELETED") SET DELETED OFF * Find a deleted record, perhaps to recycle it LOCATE FOR DELETED() RECALL NEXT 1 * Stuff some data into it GATHER MEMVAR * Now clean up SET DELETED &cOldDeleted |
See Also |