Help with mySQL database by perl script

Hello;

I was trying to set up a mysql database using following script, but never went through. The code seems fine without any syntax error as I tested it:

perl -c Brapa0101-db.pl
Brapa0101-db.pl syntax OK

However, whenever I run it, an error message was tossed out:

DBD::mysql::st execute failed: called with 9 bind variables when 0  are needed at Brapa0101-db.pl.bk line 45, <FILE> line  41174.

Could any expert help me through this problem? Thanks a lot!
Here is my code:

#!/usr/bin/perl -w

use strict;
use DBI;

# # # # # # # # # # # # # # # #  # # # # # # # # # # # # # # 
#The database "Brapa0101_db" has been created with mysql
#mysql> CREATE database Brapa0101_db;
# # # # # # # # # # # # # # # #  # # # # # # # # # # # # # # 

my $DataBaseName="Brapa0101_db";
my $DataBaseHost="localhost";
my $MySQLUser="myql_account";
my $MySQLUserPass="passwrdxyzt";
my $dsn="DBI:mysql";
my $Table="table01" ;
    

my $dbh = DBI->connect("$dsn:$DataBaseName:$DataBaseHost", $MySQLUser, $MySQLUserPass) 
            or die "Cannot connect: " . $DBI::errstr;
   my $sql = qq/INSERT INTO $Table 
                      (run, geneid,            seqtype,     scaffold,  seqstart, seqend, seqstrand,  seqlength, cdsseq)
              VALUES( int, char(20) primary key, char(20), char(100), int,   int, char(10), int,    text(40000))
            /;
##############Example rows of the file /path/to/MySQL_Study/Brapa1.1-database/Brassica_rapa.20100830.cds.tab5"
#    Run    Gene    mRNA    Scaffold    Start    End    Strand    Length    Sequence
#    1    Bra000001    [mRNA]    locus=Scaffold000001    3252        5836        +    2584    ATGGGGAAGATCTTGAAAACTAAGTCTT
#    2    Bra000002    [mRNA]    locus=Scaffold000001    6640        9120        -    2480    ATGGAGGAAGTAAGGAAGATGGGTTGTAT
#    3    Bra000003    [mRNA]    locus=Scaffold000001    21211    22012    +    801    ATGAGCTCTGTTTGTGGTAAGCTGGATTT
#    4    Bra000004    [mRNA]    locus=Scaffold000001    25599    25973    +    374    ATGATTCGCCGTCTATTCTCGTCTCTGACT.
#    5    Bra000005    [mRNA]    locus=Scaffold000001    26822    28864    -    2042    ATGGCGGCAGCTAGACGATT..
#    6    Bra000006    [mRNA]    locus=Scaffold000001    29480    29791    -    311    ATGTC...............
my $sth = $dbh->prepare($sql);

my $file_name="/path/to/MySQL_Study/Brapa1.1-database/Brassica_rapa.20100830.cds.tab5";

open(FILE, "<$file_name") or die("Cannot open the file named $file_name to read!");
     
foreach my $line (<FILE>) {
    # next if $_=~ m/Run\t/;                #This $_ has caused many headaches on me, 
    
     next if $line=~ m/Run\t/;                #This is the right syntax 
     chomp $line;
  my @fields = split(/\t/, $line);
    $sth->execute(@fields);
}

while (my $row = $sql->fetchrow_arrayref) {
        print join("\t", @$row), "\n";
    }
$dbh->disconnect;

You can't pass an array to execute(). A normal way to execute a statement is:

my $sth = $dbh->prepare($sql);
$sth->execute();
1 Like

Thanks Monster!
Actually I copied this line from somewhere and thought it would work.
After I removed the array parameters for execute, there was another error:

DBD::mysql::st execute failed: You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use near 'int, char(20) primary key, char(20), char(100), int,   int, char(10), int,    te' 
at line 3 at Brapa0101-db.pl line 45, <FILE> line 41174.

Can I ask how I can get the code working ?

The problem with the code is that the INSERT statement does not have placeholders. It has the column datatypes instead.

If you put placeholder characters ("?"), then Perl DBI will bind your array "@fields" to those and execute the statement.

So, if your tab-delimited data file looks like this:

$
$ cat Brassica_rapa.20100830.cds.tab5
Run     Gene    mRNA    Scaffold        Start   End     Strand  Length  Sequence
1       Bra000001       [mRNA]  locus=Scaffold000001    3252    5836    +       2584    ATGGGGAAGATCTTGAAAACTAAGTCTT
2       Bra000002       [mRNA]  locus=Scaffold000001    6640    9120    -       2480    ATGGAGGAAGTAAGGAAGATGGGTTGTAT
3       Bra000003       [mRNA]  locus=Scaffold000001    21211   22012   +       801     ATGAGCTCTGTTTGTGGTAAGCTGGATTT
4       Bra000004       [mRNA]  locus=Scaffold000001    25599   25973   +       374     ATGATTCGCCGTCTATTCTCGTCTCTGACT.
5       Bra000005       [mRNA]  locus=Scaffold000001    26822   28864   -       2042    ATGGCGGCAGCTAGACGATT..
6       Bra000006       [mRNA]  locus=Scaffold000001    29480   29791   -       311     ATGTC...............
$
$

then your Perl DBI program should be something like this:

#!/usr/bin/perl -w
use strict;
use DBI;
my $DataBaseName="Brapa0101_db";
my $DataBaseHost="localhost";
my $MySQLUser="myql_account";
my $MySQLUserPass="passwrdxyzt";
my $dsn="DBI:mysql";
my $Table="table01" ;
    
my $dbh = DBI->connect("$dsn:$DataBaseName", $MySQLUser, $MySQLUserPass) or die "Cannot connect: " . $DBI::errstr;
my $sql = qq{INSERT INTO $Table (run, geneid, seqtype, scaffold, seqstart, seqend, seqstrand, seqlength, cdsseq)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)};
my $sth = $dbh->prepare($sql);
my $file_name="/path/to/MySQL_Study/Brapa1.1-database/Brassica_rapa.20100830.cds.tab5";
open (FILE, "<", $file_name) or die "Cannot open the file named $file_name to read: $!";
foreach my $line (<FILE>) {
  next if $line=~ m/Run\t/;
  chomp $line;
  my @fields = split(/\t/, $line);
  $sth->execute(@fields);
}
close (FILE) or die "Can't close $file_name: $!";
$sth->finish();
$dbh->disconnect();

I couldn't test it though, as I don't have DBI or MySQL on my system.

tyler_durden

1 Like

Thank you so much Durden! It works now.

By the way, can I ask another question to create both the database and the tables, especially the tables, within perl script? What I meant is to integrate the mysql code(commented in my first post)

mysql> CREATE DATABASE Brapa0101_db; 
mysql> CREATE TABLE table01 (
         run int NOT NULL AUTO_INCREMENT  PRIMARY KEY, geneid VARCHAR(20), seqtype VARCHAR(50), scaffold VARCHAR(50),  
         seqstart INT(11), seqend INT(11), seqstrand VARCHAR(1), seqlength INT(11), cdsseq TEXT
         ); 

into the perl code. But I am not sure how to realize this idea. The reasons are:
1) It seems it can be done to me as for my learning purpose;
2) If it is done in perl script, then there is no need to go back and forth from mysql (to check the columns and the variable type etc) to my editor while writing the perl code. Here in your code the place holders did the trick, but if all are in perl code, it can be easier to control, especially with the split and joint functions.
3) Through this way, I can have full use of MySQL and do not need to go to the MySQL console;

Is this a dump question? Thanks again!

Yifang

No it is not a dumb question.
You could just plug in those statements once you connect to your data source and get a handle for that connection:

$dbh->do("CREATE DATABASE Brapa0101_db");
$dbh->do("CREATE TABLE table01 (
            run        INT NOT NULL AUTO_INCREMENT  PRIMARY KEY,
            geneid     VARCHAR(20),
            seqtype    VARCHAR(50),
            scaffold   VARCHAR(50),  
            seqstart   INT(11),
            seqend     INT(11),
            seqstrand  VARCHAR(1),
            seqlength  INT(11),
            cdsseq     TEXT)"
        );

tyler_durden

1 Like

This is what I meant, and really great! Thanks a lot again!
Yifang

Delete because of redundancy