Recipe 14.1. Making and Using a DBM File
Author: Tom Christiansen & Nathan Torkington
Date: 1999-07-02T01:42:46Z

#

| Chapter 14 Database Access |

## 14.1. Making and Using a DBM File

### Problem

You want to create, populate, inspect, or delete values in a DBM database.

### Solution

Use `dbmopen` or `tie` to open the database and make it accessible through a hash. Then use the hash as you normally would. When you're done, call `dbmclose` or `untie`.

#### dbmopen

    use DB_File;                      # optional; overrides default
    dbmopen %HASH, $FILENAME, 0666    # open database, accessed through %HASH
        or die "Can't open $FILENAME: $!\n";

    $V = $HASH{$KEY};                 # retrieve from database
    $HASH{$KEY} = $VALUE;             # put value into database
    if (exists $HASH{$KEY}) {         # check whether in database
        # ...
    }
    delete $HASH{$KEY};               # remove from database
    dbmclose %HASH;                   # close the database

#### tie

    use DB_File;                      # load database module

    tie %HASH, "DB_File", $FILENAME   # open database, to be accessed
        or die "Can't open $FILENAME:$!\n";    # through %HASH

    $V = $HASH{$KEY};                 # retrieve from database
    $HASH{$KEY} = $VALUE;             # put value into database
    if (exists $HASH{$KEY}) {         # check whether in database
        # ...
    }
    delete $HASH{$KEY};               # delete from database
    untie %hash;                      # close the database

### Discussion

Accessing a database as a hash is powerful but easy, giving you a persistent hash that sticks around after the program using it has finished running. It's also much faster than loading in a new hash every time; even if the hash has a million entries, your program starts up virtually instantaneously.

The program in Example 14.1 treats the database as though it were a normal hash. You can even call `keys` or `each` on it. Likewise, `exists` and `defined` are implemented for tied DBM hashes. Unlike a normal hash, a DBM hash does not distinguish between those two functions.

#### Example 14.1: userstats

    #!/usr/bin/perl -w
    # userstats - generates statistics on who is logged in.
    # call with an argument to display totals

    use DB_File;

    $db = '/tmp/userstats.db';       # where data is kept between runs

    tie(%db, 'DB_File', $db)         or die "Can't open DB_File $db : $!\n";

    if (@ARGV) {
        if ("@ARGV" eq "ALL") {
            @ARGV = sort keys %db;
        }
        foreach $user (@ARGV) {
                print "$user\t$db{$user}\n";
        }
    } else {
        @who = `who`;                                   # run who(1)
        if ($?) {
            die "Couldn't run who: $?\n";               # exited abnormally
        }
        # extract username (first thing on the line) and update
        foreach $line (@who) {
            $line =~ /^(\S+)/;
            die "Bad line from who: $line\n" unless $1;
            $db{$1}++;
        }
    }

    untie %db;

We use who to get a list of users logged in. This typically produces output like:

    gnat     ttyp1   May 29 15:39   (coprolith.frii.com)

If the userstats program is called without any arguments, it checks who's logged on and updates the database appropriately.

If the program is called with arguments, these are treated as usernames whose information will be presented. The special argument `"ALL"` sets `@ARGV` to a sorted list of DBM keys. For large hashes with many keys, this is prohibitively expensive - a better solution would be to use the BTREE bindings of DB_File described in Recipe 14.6.

### See Also

The documentation for the standard modules GDBM_File, NDBM_File, SDBM_File, DB_File, also in Chapter 7 of Programming Perl; perltie (1); the section on "Using Tied Variables" in Chapter 5 of Programming Perl; the discussion on the effect of your `umask` on file creation in Recipe 7.1; Recipe 13.15

14.0. Introduction |  | 14.2. Emptying a DBM File