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

Dear Monks,

I know the title it does not make sense, but this is my main question/problem.

The question evolves several parts and a lot of explanation so please bear with me as it will be a long one with a lot of analysis in between.

I have a working code with do commands and prepare. I know that do is exactly the same with prepare and execute together. I have read O'Reilly's CD bookshelfs/5.5. do( ) Versus prepare( ) that there is no difference between them, unless if you are going to apply multiple loops. Where in this case do will apply multiple requests in comparison to prepare which will execute all requests at once.

So I thought it would be a good idea to become more familiar with prepare and start using it more frequently and not only on INSERT,SELECT and UPDATE statements but everywhere. At this point there is my first problem. I am using prepare on the same piece of code that do works fine and although that I do not get any errors I do get a hash value not an integer. Sample of code provided under:

my $databases = $dbh->do("SHOW DATABASES LIKE '".$DATABASE."'") or die "Error: " .dbh->errstr. "\n"; my $databases = $dbh->prepare("SHOW DATABASES LIKE ? ") or die "Error: " .dbh->errstr. "\n"; $databases->execute($DATABASE) or die "Error: " . $databases->errstr. "\n"; print "This is the databases: ".$databases."\n";

Output of do command:

This is the databases: 1

Output of prepare command

This is the databases: DBI::st=HASH(0xe47058)

Complete working sample code can be found under:

#!/usr/bin/perl use strict; use warnings; use DBD::mysql; $|=1; #flush every time the program my $DATABASE = 'xxxx'; my $USERNAME = 'xxxx'; my $TABLE = 'xxxx'; my $HOST = 'xxxx'; my $PORT = 'xxxx'; my $PASS = 'xxxx'; my $checkExist; sub mysql { my $dbh = DBI->connect("dbi:mysql::".$HOST.":".$PORT."", "".$USERNAME."", "".$PASS."", { 'PrintError' => 1, 'RaiseError' => 1 } ) or die "Could not connect to ". $HOST .": ". $DBI::errstr ."\n"; my $databases = $dbh->do("SHOW DATABASES LIKE '".$DATABASE."'") or die "Error: " .dbh->errstr. "\n"; =comment my $databases = $dbh->prepare("SHOW DATABASES LIKE ? ") or die "Error: " .dbh->errstr. "\n"; $databases->execute($DATABASE) or die "Error: " . $databases->errstr. "\n"; =cut print "This is the databases: ".$databases."\n"; exit(); if ($databases eq 1) { printf "Database: ". $DATABASE ." exists not creating!\n"; } else { printf "Database: ". $DATABASE ." does not exist creating!\n"; $checkExist = $dbh->prepare("CREATE DATABASE IF NOT EXISTS `".$DAT +ABASE."`") or die "Could not create the: ".$DATABASE." error: ". $dbh->er +rstr ."\n"; if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } } # End of else $dbh->do("USE ".$DATABASE."") or die "Error: " .dbh->errstr. "\n"; my $tables = $dbh->do("SHOW TABLES FROM `".$DATABASE."` WHERE Tabl +es_in_".$DATABASE." LIKE '".$TABLE."'") or die "Error: " .dbh->errstr +. "\n"; print "Tables do: ".$tables."\n"; $tables = $dbh->prepare("SHOW TABLES FROM `".$DATABASE."` WHERE Ta +bles_in_".$DATABASE." LIKE '".$TABLE."'") or die "Error: " .dbh->errs +tr. "\n"; $tables->execute() or die "Couldn't execute statement: " . $tables->errstr; print "Tables prepare: ".$tables."\n"; if ($tables eq 1) { printf "Table: ".$TABLE." exists not creating!\n"; } else { printf "Table: ".$TABLE." does not exist creating!\n"; $checkExist = $dbh->prepare("CREATE TABLE IF NOT EXISTS `".$TABLE. +"` ( `id` int(11) NOT NULL AUTO_INCREMENT, `UnixTime` int(11) NOT NULL, `losses` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREM +ENT=1 ;"); if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } } # End of else my $range = 50; my $minimum = 100; my $random_number = int(rand($range)) + $minimum; my $time = time(); my $losses = $time . ' ' . $random_number; $checkExist = $dbh->prepare("INSERT IGNORE INTO `".$TABLE."` (`Uni +xTime`, `losses`) VALUES ('".$time."','".$random_number."') "); if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } $checkExist->finish(); $dbh->disconnect(); return $losses; } # End of mysql sub my $output = &mysql(); print "This is the output: ".$output."\n";

At this point I think the syntax is correct because if I only apply do it works just fine. So can someone elaborate me more why I can not get the same result with do and prepare?

Thank you all for your time and effort assisting me.

Seeking for Perl wisdom...on the process...not there...yet!

Replies are listed 'Best First'.
Re: Can not get the same output from $dbh->do and $dbh->prepare
by Corion (Patriarch) on May 24, 2014 at 21:54 UTC

    Placeholders do only work for column values. The basic rule is that the database must be able to construct a query plan when it sees the prepared statement with only the placeholders. Statements with placeholders are unlikely to work where a table name or column name is expected.

    So your best approach is to interpolate the table name and then do a ->selectall_arrayref. Also, you might want to take a look at the catalog methods in DBI, which tell you about tables and columns in a fashion independent of the database.

      To: Corion,

      It starts to make more sense, I was not aware of this detail and where ever I read I could not find this details. I assumed since do and prepare are the same maybe I could apply them the same way. Thank you for your time and effort replying to my question.

      Seeking for Perl wisdom...on the process...not there...yet!
Re: Can not get the same output from $dbh->do and $dbh->prepare
by boftx (Deacon) on May 24, 2014 at 21:57 UTC

    RTF(ine)M. "do" does not return data from queries. DBI

    It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.

      To: boftx,

      Well first of all the link that you provide is not working. Second of all not all of us can find and understand the information that clearly and that fast.

      But any way, thank you for your time and effort replying to my question.

      Seeking for Perl wisdom...on the process...not there...yet!

        The link just worked for me, but then again, CPAN has been a bit flaky lately.

        That said, here is the wording from the relevant section:

        do $rows = $dbh->do($statement) or die $dbh->errstr; $rows = $dbh->do($statement, \%attr) or die $dbh->errstr; $rows = $dbh->do($statement, \%attr, @bind_values) or die ... Prepare and execute a single statement. Returns the number of rows aff +ected or undef on error. A return value of -1 means the number of row +s is not known, not applicable, or not available. This method is typically most useful for non-SELECT statements that ei +ther cannot be prepared in advance (due to a limitation of the driver +) or do not need to be executed repeatedly. It should not be used for + SELECT statements because it does not return a statement handle (so +you can't fetch any data).
        The key to using do is that it can only return the number of row affected by an operation. This makes it ideal for INSERT, UPDATE and DELETE, but it simply can't do what you want when it comes to a SELECT statement.

        Sorry if the first post came across as a bit harsh, I should have put a smiley in there somewhere. Now that you beginning your endeavor to grok "DBI" you should probably a browser window open to the CPAN docs for it constantly. Hell, I still go back and check details on calls.

        It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
        not all of us can find and understand the information that clearly and that fast.

        Interesting. The first thing any user should be taught (after switching on and logging in/out) is the man command. Were you not?

        Of course you may use a platform which doesn't feature this brilliant command, but that's OK because every perl user's first lesson should include a reference to perldoc. Did yours?

        The thing is that even if your lessons did not include mention of these 2 fundamental commands, your favourite search engine should have helped.

        You'll notice that the first result there comes straight back here to perlmonks. Further, the second is the page to which boftx linked. Both are excellent resources.

        It would be my recommendation that you take the time to familiarise yourself with man and perldoc and get to grips with the query syntax of your favourite search engine. That way many answers can be found and much time saved.

Re: Can not get the same output from $dbh->do and $dbh->prepare
by taint (Chaplain) on May 25, 2014 at 03:14 UTC
    Greetings, thanos1983

    While this isn't a direct answer to do vs prepare vs {...}. I was investigating a Perl module written by Jenda for a project I'm working on, and happened upon another Module by Jenda (DBIx::Declare). It seemed to provide a pretty nice interface to dealings with databases, and may even help you in your current, or future dealings. But, in any event, the author's POD seemed to infer prepare, as the method. So maybe this is the correct procedure, in the case you're working with now. Or maybe the authors module would make your current case easier.

    Best wishes.

    --Chris

    ¡λɐp ʇɑəɹ⅁ ɐ əʌɐɥ puɐ ʻꜱdləɥ ꜱᴉɥʇ ədoH

      Greetings Chris,

      This link is really interesting also the one about don't that you have port under. It is really impressive how many modules Perl has. Thank you for your time and effort reading and replying to my post.

      Seeking for Perl wisdom...on the process...not there...yet!
Re: Can not get the same output from $dbh->do and $dbh->prepare
by taint (Chaplain) on May 25, 2014 at 20:38 UTC
    While reading some of the Module Reviews here at PM. I happened to run across Acme::Don't (CPAN Acme::Don't), by Damian Conway. It is, as it's name infers; the opposite of do. So I felt it worth a mention here.

    Sorry. I couldn't resist.

    --Chris

    ¡λɐp ʇɑəɹ⅁ ɐ əʌɐɥ puɐ ʻꜱdləɥ ꜱᴉɥʇ ədoH