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

I get a 500 error when I try to run this. It is my first attempt to use DBI or a database.

#!/usr/local/bin/perl use CGI; use DBI; my $dbh; $dbh = DBI->Connect("DBI:mysql:strossus:localhost","strossus","passwor +d"); my $table = $dbh->prepare qq' CREATE TABLE players (realname CHAR(20), = gold CHAR(40))'); $dbh->disconnect();

Replies are listed 'Best First'.
(Ovid) Re: dbi 500 error
by Ovid (Cardinal) on Jan 18, 2002 at 02:51 UTC

    If you're getting a 500 error, this tells me you are running this through a Web server. You're not sending any output back to the client, so your error log is probably complaining about "Premature end of script headers". That doesn't mean your program is wrong, just that you either need to run it from the command line or convert it to a proper CGI program. However, I wouldn't have a CGI program issuing "CREATE TABLE" commands :)

    Assuming your shebang line is correct, here's a simple, complete CGI program:

    #!/usr/local/bin/perl -wT use strict; use CGI qw/:standard/ print header, start_html( -title => 'Test program' ), h1( 'Hello world' ), end_html;

    Update: Ack! I see a problem in your program:

    my $table = $dbh->prepare qq' CREATE TABLE players (realname CHAR(20), = gold CHAR(40))');

    Take a close look at your single quotes! It looks like you missed a parentheses.

    my $table = $dbh->prepare( qq' CREATE TABLE players (realname CHAR(20), gold CHAR(40))');

    Further, I'm already seeing some database design issues that you need to think about. Include a non-identifying ID for the player. If you use the realname as the ID, you can't easily update it.

    create table players ( player_id INTEGER NOT NULL, firstname VARCHAR(15), lastlast VARCHAR(20), gold INTEGER );

    Now, have every table that needs to link to the players table use the player_id. You can then change the other data at will.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      I'm kinda new at Perl myself (being reformed from days as an amatuer Java geek). Chromatic (an old college friend) refered me to perlmonks. I have moved to a new server and am consitently getting 500 errors trying to run simple scripts (even hellocgi.cgi that comes with Apache bundled with Indigo Perl). I can execute the scripts fine, locally, using Apache, but on my server they consistently throw 500 errors. File permissions are set to 775, and the shebang is all good. I can't get it to work, but Ovid said something that made me want to ask a question:

      Ovid wrote:
      You're not sending any output back to the client, so your error log is probably complaining about "Premature end of script headers". That doesn't mean your program is wrong, just that you either need to run it from the command line or convert it to a proper CGI program.

      The program works from the command line (obviously, PuTTY won't render the HTML). And it works locally. The phrase "convert it to a proper CGI program" caught my attention, though. In Java everything got compiled into classes. I can't imagine needing to do that to a Perl script. What did you mean by the statement?

      Thanks,
      Mike

        Hi Mike,

        Note: this code is untested.

        What did you mean by [convert it to a proper CGI program]?

        That's a straightforward question, but regrettably, the answer is not as clear. Typically, when working with in a CGI environment, several issues arise that may not occur in different environment. You have to worry about sending headers, formatting your output correctly, maintaining state, etc. In other words, consider what happens if you want a simple "hello, world" program:

        perl -le 'print "Hello, world!"'

        And if I want to personalize this:

        perl -e 'print "Hello, ", shift' Ovid

        Now, what happens if I want to convert that to a CGI program? The first example is easy, but I won't do it as a one-liner because that's not going to work with a Web server.

        print "Content-Type: text/plain; charset=ISO-8859-1\n\nHello, world"';

        That's roughly equivalent to the "Hello, world" program, but what do we do if we want to personalize it? We'll switch to CGI.pm to make our life easier. First, we assume the following form:

        <form action="/cgi-bin/test.cgi"> <input type="text" name="name"> <input type="submit" name="submit" value="Press me!"> </form>

        Then we read it and respond:

        #!/usr/bin/perl -T use warnings; use strict; use CGI qw(:standard); my $_name = param('name') || ''; my ($name) = $_name =~ /([[:alnum:][:space:][:punct:]]+)/; $name ||= 'Anonymous Monk'; print header, <<"END_HTML"; <html> <head><title>Greeting Page</title></head> <body><p>Hello, $name</body> </html> END_HTML

        And if we need persistence:

        #!/usr/bin/perl -T use warnings; use strict; use CGI qw(:standard); my $_name = cookie('name') || param('name') || ''; my ($name) = $_name =~ /([[:alnum:][:space:][:punct:]]+)/; $name ||= 'Anonymous Monk'; my $cookie = cookie( -name => 'name', -value => $name ); print header(-cookie => $cookie), <<"END_HTML"; <html> <head><title>Greeting Page</title></head> <body><p>Hello, $name</body> </html> END_HTML

        I could go on further, but I think you get the basic idea. The last listing is where I got to from a simple command line "hello, world" script to a CGI program. If you see some strange things in the last script, note my .sig line which has a link to my CGI course. That should answer many questions. In any event, I hope this answered your question.

        Cheers,
        Ovid

        New address of my CGI Course.
        Silence is Evil (feel free to copy and distribute widely - note copyright text)

      I have taken your advice into consideration and have come up with my new version(that does not create and errors).
      #!/usr/local/bin/perl use CGI qw/:standard/; use DBI; print header, start_html( -title => 'Test ' ), h1( 'Hello world' ), end_html; my $dbh; $dbh = DBI->Connect("DBI:mysql:strossus:localhost","strossus","******* +*"); my $table = $dbh->prepare (qq' CREATE TABLE players (firstname CHAR(20), lasttname CHAR(20), email CHAR(50), player INTEGER NOT NULL,, hitp INTEGER, maxhtipp INTEGER, minatt INTEGER, maxatt INTEGER, exp INTEGER, gold INTEGER)'); $table->execute(); $talbe->finish(); $dbh->disconnect();

      Edited 2002-01-17 by Ovid to hide password :(

        I just edited your post to hide your password. Be careful!

        First, like I said, I still wouldn't want to run a CREATE TABLE command through a CGI script. What happens when someone calls your program again? It will try to create a table that already exists. I've never tried to do that, so I can't guess what will happen. I suspect that things will die a horrible death, but no guarantees.

        Second, you should either check all of your DBI calls for success, or add the RaiseError attribute to your connect call. See trs80's response below.

        Last, you'll still want to have a unique, non-indentifying ID for the table.

        CREATE TABLE players ( player_id INTEGER NOT NULL PRIMARY KEY, firstname VARCHAR (20) NOT NULL, lastname VARCHAR (20) NULL, ... more stuff here ... ) CREATE TABLE foo ( foo_id INTEGER NOT NULL PRIMARY KEY, player_id INTEGER NOT NULL REFERENCES players (player_id), stuff VARCHAR(30) NOT NULL )

        Learning databases is a good thing, but be sure to learn them well. It's very easy to do thing wrong. Life is Hell for the programmer who is forced to work with a poorly designed database.

        Update: I just tossed in the other table to show you how things things work. If your database will be simple enough that you only need one table, it's not necessary. If, however, it's going to be complex, you'll want to start learning these design issues.

        Cheers,
        Ovid

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: dbi 500 error
by trs80 (Priest) on Jan 18, 2002 at 03:15 UTC
    The one followup explaining the need for the correct
    header output using CGI is correct, but the code example
    you posted has some errors as well.
    #!/usr/local/bin/perl use CGI; use DBI; my $dbh; $dbh = DBI->Connect("DBI:mysql:strossus:localhost","strossus", "********"); my $table = $dbh->prepare qq' CREATE TABLE players (realname CHAR(20), = gold CHAR(40))'); $dbh->disconnect();
    First thing is the connect method in DBI it is lower case
    you are using Connect which is not valid.
    The DSN is incorrect see code below for correct syntax.
    The use of a ' as a delimiter an SQL statement is
    dangerous since ' is a common character in SQL. I prefer ~
    in my code or !
    There also seems to be a missing ( at the start of the
    prepare statement.
    The prepared statement is never executed. You need to call
    $table->execute if you want it to take action.

    I would rewrite this block as
    #!/usr/local/bin/perl use strict; use CGI qw/:standard/; my $cgi = CGI->new(); print $cgi->header; use DBI; my $dbh; $dbh = DBI->connect('DBI:mysql:strossus@localhost', "strossus","********", { RaiseError => 1 }); my $table = $dbh->prepare(qq~ CREATE TABLE players ( realname CHAR(20), gold CHAR(40) )~ ); $table->execute(); $dbh->disconnect();
    Warning I did minimal testing on this code :^) and I
    didn't get into table design like one of the other
    responders did. Proper table design is very important and
    beyond the scope of this reply.
Re: dbi 500 error
by George_Sherston (Vicar) on Jan 18, 2002 at 16:31 UTC
    It's a little OT, because doing this wouldn't have helped fix the particular problem, but I'd encourage you to use error checking in DBI, that is, add the folloing or statements so that if your DBI calls fail the script will stop and give you some useful info.
    $dbh = DBI->Connect("DBI:mysql:strossus:localhost","strossus","passwor +d") or die $DBI::errstr; my $table = $dbh->prepare qq' CREATE TABLE players (realname CHAR(20), = gold CHAR(40))') or die $dbh->errstr;
    I'd also encourage use of
    use CGI::Carp qw(fatalsToBrowser warningsToBrowser); print header; warningsToBrowser(1);
    at the top of the script, so that this useful information gets dumped to your screen right away.

    And of course (this is probably the most useful part of my post, and I commend it out of much pain through not following such good advice myself) use strict and warnings

    § George Sherston