HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Perl DBI insert of hash

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
dbiinserthashperl

Problem

How can this method that inserts a hashref into a database table be improved? It assumes that the columns of the database table are named identically to the fields in the hashref. The return value is the id field created by the insert.

sub insert(){
    my ($table, $data) = @_;
    my ($fields, $placeholders, $values) = ("", "", []);
    while (my ($field, $value) = each %$data){
        $fields.=", " if ($fields);
        $fields.=$field;
        $placeholders.=", " if ($placeholders);
        $placeholders.="?";
        push(@$values, $value);
    }
    $dbh->prepare("INSERT INTO $table ($fields) VALUES ($placeholders)")->execute(@$values);
    return $dbh->last_insert_id(undef, undef, undef, undef);
}


It assumes that $dbh is a correctly initialized global database handle.

It is used like:

&insert("animals", {
    "type"=>"cat",
    "name"=>"Patches",
    "date-of-birth"=>"November 1, 2015",
    "date-of-death"=>undef
});


Which will insert a record into the animals table:

id | type | name    | date-of-birth    | date-of-death
=====================================================
 1 | cat  | Patches | November 1, 2015 | null

Solution

This might be a good candidate to use SQL::Abstract in, as per DBIx::Class.

sub insert {
    # insert takes ( $table, \%fieldmap )
    my $sql = SQL::Abstract->new();
    my ( $query, @binds ) = $sql->insert( @_ );
    $dbh->prepare($query)->execute(@binds);
    return $dbh->last_insert_id(undef, undef, undef, undef);
}


This gives you a few easy features that may come in handy in the future
if you change your database, like:

  • easily change quoting character for tables/fields



  • guard against injection abuse in user-specified key names, because your code currently assumes all keys will be safe. But this will not necessarily be true, and is a vulnerability target even under taint

Code Snippets

sub insert {
    # insert takes ( $table, \%fieldmap )
    my $sql = SQL::Abstract->new();
    my ( $query, @binds ) = $sql->insert( @_ );
    $dbh->prepare($query)->execute(@binds);
    return $dbh->last_insert_id(undef, undef, undef, undef);
}

Context

StackExchange Code Review Q#120040, answer score: 6

Revisions (0)

No revisions yet.