ShayShay has asked for the wisdom of the Perl Monks concerning the following question:

I'm having a bit of a problem with a project that I'm hoping you all can help me out with. I've looked over some of the documentation and done google searches, but I still can't get it to work.

I'm using SQLite to try to insert a row into a table. I've got variables $gi, $orgName, and $nc that I want to use in my insert statement. I've tried several various ways of writing the statement, including using ? as values and undef afterwards, as well as playing with the " marks. Nothing seems to work.

I'm getting the error:

DBD::SQLite::db prepare failed: near "NC": syntax error(1) at dbdimp.c line 271 at C:\Perl\bin\getAllFiles.pl line 31, <FILE> line 3328.
Can't call method "execute" on an undefined value at C:\Perl\bin\getAllFiles.pl line 40, <FILE> line 3328.

Here's a condensed version of the code from "getAllFiles.pl":

use Cwd; use Net::FTP; use DBI; use strict; sub dbConnect{ my ($database, $username, $password, $hostname) = @_; my $db = DBI->connect("DBI:SQLite:$database:$hostname", $username, + $password) || die "Cannot connect to host database.".$DBI::errstr; return $db; } sub dbDisconnect{ my ($db) = @_; $db->disconnect; } sub dbQuery{ my ($query) = @_; print $query; my($database) = "myDB"; my($username) = "username"; my($password) = "password"; my($hostname) = "myHost.com"; my $db = dbConnect($database, $username, $password, $hostname); $query = $db->prepare($query); #LINE 31 $query->execute; #LINE 40 $query->finish; dbDisconnect($db); } my $gi = "11111111"; my $orgName = "some bacteria"; my $nc = "NC_000000"; my $query = "INSERT INTO ORGANISM (ORG_NAME, GI, NC) VALUES ('$gi', '$ +orgName', '$nc')"; dbQuery($query);

Replies are listed 'Best First'.
Re: Query Formatting
by ikegami (Patriarch) on Dec 05, 2007 at 22:48 UTC
    Another error is that you don't convert your parameters from text to SQL. That could be done through $db->quote or through replaceable parameters.
    sub dbQuery{ my $query = shift @_; my($database) = "myDB"; my($username) = "username"; my($password) = "password"; my($hostname) = "myHost.com"; my $db = dbConnect($database, $username, $password, $hostname); $query = $db->prepare($query); $query->execute(@_); $query->finish; dbDisconnect($db); } my $gi = "11111111" my $orgName = "some bacteria" my $nc = "NC_000000" my $query = "INSERT INTO ORGANISM ORG_NAME, GI, NC VALUES (?, ?, ?)"; dbQuery($query, $gi, $orgName, $nc);

    That will fix a problem unrelated to the one you're asking about.

Re: Query Formatting
by eserte (Deacon) on Dec 05, 2007 at 22:40 UTC
    It should be VALUES, not VAUES.
      Yeah... typo... but it still doesn't work after fixing those...
Re: Query Formatting
by KurtSchwind (Chaplain) on Dec 05, 2007 at 22:55 UTC

    Another issue:

    Your Values('$gi' . . . won't replace $gi with "11111111" because it's enclosed in single ticks.

    Update ikegami rightly pointed out that the outside string was double quoted.

    --
    I used to drive a Heisenbergmobile, but every time I looked at the speedometer, I got lost.
      No, it's in a double-quoted string literal.
Re: Query Formatting
by tcf03 (Deacon) on Dec 06, 2007 at 10:01 UTC
    This should do what you are looking to do.

    #!/usr/bin/perl use strict; use warnings; use DBI; sub dbConnect{ my ($database, $username, $password, $hostname) = @_; my $db = DBI->connect("DBI:SQLite:$database:$hostname", $username, $password) || die "Cannot connect to host database.".$DBI::errstr; return $db; } sub dbDisconnect{ my ($db) = @_; $db->disconnect; } sub dbINSERT{ my $table = shift; my $set = shift; my @values = @_; my($database) = "myDB"; my($username) = "username"; my($password) = "password"; my($hostname) = "myHost.com"; my $db = dbConnect($database, $username, $password, $hostname); my $vals = join',', map { $db->quote($_) } @values; my $query = qq|INSERT into $table ($set) VALUES ($vals)|; print "$query\n"; $query = $db->prepare($query); #LINE 31 $query->execute; #LINE 40 $query->finish; dbDisconnect($db); } sub dbUPDATE{ # Do updates here } sub dbDELETE{ # Do deletes here } dbINSERT('ORGANISM', 'ORG_NAME, GI, NC', "11111111", "some bacteria", +"NC_000000");
    Though, I would move the db connection out of the insert/delete/update subs and just do something like this
    #!/usr/bin/perl use strict; use warnings; use DBI; sub dbConnect{ my ($database, $username, $password, $hostname) = @_; my $db = DBI->connect("DBI:SQLite:$database:$hostname", $username, $password) || die "Cannot connect to host database.".$DBI::errstr; return $db; } sub dbINSERT{ my $db = shift; my $table = shift; my $set = shift; my @values = @_; my $vals = join',', map { $db->quote($_) } @values; my $query = qq|INSERT into $table ($set) VALUES ($vals)|; print "$query\n"; $query = $db->prepare($query); #LINE 31 return ( $query->execute ) : 0 : 1; } sub dbUPDATE{ # Do updates here } sub dbDELETE{ # Do deletes here } my $db = dbConnect("myDB", "username", "password", "myHost.com"); my $status = ( dbINSERT($db, 'ORGANISM', 'ORG_NAME, GI, NC', "11111111 +", "some bacteria", "NC_000000") == 0 ) ? 0 : 1; END { $db->disconnect }
    Its untested, but should work fine for you.

    Update added return code from insert and removed disconnect sub. After re-reading your original post - you may wish to re-add the disconnect sub ( and remove the END block ) as this looks to be part of a larger program

    Ted
    --
    "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
      --Ralph Waldo Emerson
      one more addition you may want to consider is setting $db->{RaiseError} or $db->{PrintError} or both.
      sub dbConnect{ my ($database, $username, $password, $hostname) = @_; my $db = DBI->connect("DBI:SQLite:$database:$hostname", $username, $password) || die "Cannot connect to host database.".$DBI::errstr; $db->{RaiseError} = 1; $db->{PrintError} = 1; return $db; }
      Ted
      --
      "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
        --Ralph Waldo Emerson