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

Monks, I have a code inside my while loop with a counter, and it should increment every row starting from 0 up to 100 in a database but when I run the code it is setting all the rows to the last value 100, how could I do this? Any help?
$c++; while(code here){ And I do my update here }

Replies are listed 'Best First'.
Re: Increment DB using Perl
by Joost (Canon) on Mar 08, 2005 at 16:27 UTC
Re: Increment DB using Perl
by jZed (Prior) on Mar 08, 2005 at 16:27 UTC
    You better show us your real code (or a boiled down piece of it.

    It's hard to say, but it seems like you want something like

    for my $c(0..100) { # do something with $c; }
      Sorry, here is the code I am testing
      #!/usr/bin/perl -w use strict; use DBI; # Set up database connection my $user = "content"; my $pass = "content"; my $dbh = DBI->connect("DBI:ODBC:LocalServer",$user, $pass, {RaiseErro +r => 1}); my $dbh2 = DBI->connect("DBI:ODBC:LocalServer",$user, $pass, {RaiseErr +or => 1}); my $new_id = 0; my $sql = "select id from request"; my $sql2 = ''; my $sth = $dbh->prepare($sql); my $sth2 = ''; my $sql_data = ($sth->execute() || die $sth->errstr); while (my $pointer = $sth->fetchrow_hashref) { $new_id++; $sql2 = "UPDATE request SET ID='$new_id'"; $sth2 = $dbh2->prepare($sql2); $sth2->execute() || die $sth2->errstr; }
        First, you don't need two database handles - you can almost certainly just use two statement handles on the same database handle. Second, don't put quotes around '$new_id' -- quotes are for delimiting strings in SQL, not for numbers. Third, don't do the prepare inside the loop, the whole point is prepare only needs to be done once. Fourth, you don't need ||die $sth2->errstr, you have RaiseError on. Fifth, what are you expecting to happen with $sql_data and $pointer, you never use them? You better describe what you want to happen. But thanks for the code :-).
        The problem is not with code, but the SQL.

        You're setting the ID to $new_id for EVERY row. That means you're only seeing the last result.
        --------------
        It's sad that a family can be torn apart by such a such a simple thing as a pack of wild dogs
        "UPDATE request SET ID='$new_id'";
        Always sets ALL rows in request to $new_id. You should use some kind of WHERE clause to limit the effect, but that might not help you here. Also, it isn't exactly good practice to change the primary keys of existing rows (I'm assuming request.id is the primary key).

        Maybe you want to skip the SELECT and just do 1 query like

        UPDATE request set ID=ID+1;
        updated: that last piece of code doesn't do what is wanted.
Re: Increment DB using Perl
by tall_man (Parson) on Mar 08, 2005 at 18:23 UTC
    I gather that you have a DB table designed without any unique keys and you are trying to add the keys after the fact with an update. My suggestion is that you dump all the table data out to a file, create a new table with a primary key attribute for ID, combine the data with the sequential ID's using a script, and then populate the table with the new data.

    Update: You could also do it by inserting into a new table with values from the old one, like this:

    use strict; use warnings; use DBI; # Set up database connection my $user = "content"; my $pass = "content"; my $dbh = DBI->connect("DBI:ODBC:LocalServer",$user, $pass, {RaiseErro +r => 1}); my $new_id = 0; # Assumes the new table request2 has the same layout as the first one. # The ID should be declared as a primary key for this table. # I assume it was not declared that way in table request. my $sth = $dbh->prepare(q{SELECT * FROM request}); # There should be a placeholder for each value in the table. my $sth2 = $dbh->prepare(q{INSERT INTO request2 VALUES(?,?,?)}); my $sql_data = ($sth->execute() || die $sth->errstr); while (my $pointer = $sth->fetchrow_arrayref) { # Assumes the ID field is the first field. $pointer->[0] = $new_id; $sth2->execute(@{$pointer}); $new_id++; }

    In summary, it was a bad mistake to define an SQL table without unique keys, and the best way to recover is by getting the data into a new table.