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

Hello Monks,

I'm trying to put logic into perl coding but not able to do so for sometime now.

What I'm trying to do is

1. Open csv file

2. Insert line into Oracle table

3. If any error then

3.1 Rollback all inserts of the file

3.2 Update status table with FAILURE

3.3 Move to next file

4. If all inserts completed then

4.1 Update status table with SUCCESS

5. Commit

Could some expert monks help me out sorting this logic?
use warnings; use strict; use Text::CSV; use DBD::Oracle; my $exitStatus = 0; # Connect to database and disable autocommit my $dbAgent = OracleAgent->dbLogin(dbName); $dbAgent->connect(); $dbAgent-> setAutoCommit(0); #@csvFile holds all csv files list to load in db foreach my $file (@csvFile) { chomp ($item); &insertRecords($file); } $logFile-> ("Exit status"); #---------------- sub insertRecords { my $csv; my $fileToInsert = shift; my $row; my $SQL; my $sth; my $dbh; my $rc; open my $fh, "<", $fileToInsert or die "$filetoInsert: $!" $logFile -> ("Working under $file") while ($row = $csv->getline ($fh)) { $SQL1 = "Insert into TAB1 (sample_date, server, first, n1, n2) values (?,?,?,?,?)"; $sth = prepare($SQL1) $sth -> execute($row[0], $row[1], $row[2], $row[3], $row[4]) || { logFile($DBI::errstr); $dbAgent->rollback; $rc=0; #if error in insert then update status table $SQL3 = "Insert into STATUS (sample_date, server +, cvs_file, row_count, status) values (sysdate,$row[1],$file,$rc,'FAI +LURE')"; $sth = executeQuery($SQL3); } else { #if no error in insert then update status table an +d commit everything $SQL2 = "Insert into STATUS (sample_date, server, + cvs_file, row_count, status) values (sysdate,$row[1],$file,$rc,'SUCCESS')"; $sth = executeQuery($SQL2); $rc++; } close $fh; $dbAgent->commit;

Replies are listed 'Best First'.
Re: Perl oracle insert error handling
by Anonymous Monk on Dec 23, 2014 at 17:11 UTC

    Since you've got several syntax errors that prevent your code from even compiling, I'm guessing you're fairly new to Perl. In that case, I think you've put too much on your plate to start with. You can fix a lot of the issues with the code yourself; take a step back and approach the problem step by step. For example, Step 1: connect to the database. Put this in a script and attempt to run it:

    use warnings; use strict; use Text::CSV; use DBD::Oracle; my $exitStatus = 0; # Connect to database and disable autocommit my $dbAgent = OracleAgent->dbLogin(dbName); $dbAgent->connect(); $dbAgent-> setAutoCommit(0);

    Try to run it: Does it work, or does it print an error? If it prints an error, try to fix it, or post it here if you can't figure it out on your own. Then, Step 2, add the following to the file:

    foreach my $file (@csvFile) { chomp ($item); &insertRecords($file); } sub insertRecords { my $fileToInsert = shift; }

    Again, try to run it, and fix the problems as they show up. And so on.

    Also, remember the Basic debugging checklist, and if you need help fixing individual problems, remember How do I post a question effectively?

      Thanks for the suggestion and I 100% agree to it.

      My database connection, inserting into database, committing record everything works

      I will go with one problem at a time.

      My very first and most important problem is to have WHILE IF ($sth->err) loop working..I have changed my initial code little bit to move further.

      somehow code doesn't like 2 close $fh; in the code and still logfile says 1 row commited where zero rows inserted actually.

      while ($row = $csv->getline ($fh)) { $SQL1 = "Insert into TAB1 (sample_date, server, first, n1, n2) values (?,?,?,?,?)"; $sth = prepare($SQL1) $sth -> execute($row[0], $row[1], $row[2], $row[3], $row[4]); if ($sth->err) { $rc=0; $dbAgent->rollback(); close $fh; } $rc++; } close $fh; $dbAgent->commit;

        You only need to prepare the statements once

        #!perl use strict; use Text::CSV; use DBD::Oracle; my $csv = Text::CSV->new ( { binary => 1 } ) or die "Cannot use CSV: ".Text::CSV->error_diag (); my $dbh = dbh(); # connect my $SQL1 = "INSERT INTO TAB1 (sample_date, server, first, n1, n2) VALUES (?,?,?,?,?)"; my $sth1 = $dbh->prepare($SQL1); my $SQL2 = "INSERT INTO STATUS (sample_date,server,csv_file,row_count, +status) VALUES (sysdate,?,?,?,?)"; my $sth2 = $dbh->prepare($SQL2); my @csvFile = ('1.csv','2.csv','3.csv'); for my $file (@csvFile){ insertRecords($file); } $dbh->disconnect; sub insertRecords { my $file = shift; print "Working under $file\n"; open my $fh,'<',$file or die "$file : $!"; my $status = "SUCCESS"; my $server; my $rc = 0; while (my $row = $csv->getline ($fh)){ ++$rc; $server = $row->[1]; print join ",",@$row[0..4],"\n"; if ( $sth1->execute(@$row[0..4]) ){ # ok } else { $status = "FAILURE"; last; } }; if ($status eq 'FAILURE'){ $dbh->rollback; $rc = 0; print "ERROR - Rolled back $file\n"; } $sth2->execute($server,$file,$rc,$status); $dbh->commit; close $fh; } # connect sub dbh { my $host = "localhost"; my $sid = 'xe'; my $user = ''; my $pwd = ''; my $dsn = "dbi:Oracle:host=$host;sid=$sid"; my $dbh = DBI->connect($dsn, $user, $pwd, { AutoCommit => 0, }) or die "$!"; return $dbh }
        poj
        My database connection, inserting into database, committing record everything works

        Really? Then next time show us that code, since the code in the OP certainly doesn't work.

Re: Perl oracle insert error handling
by chacham (Prior) on Dec 23, 2014 at 16:44 UTC

    Side note: The first query ($SQL1) is prepared and executed, avoiding dynamic SQL and its ills. Bravo! But the second query ($SQL3) uses dynamic SQL. Perhaps you shopuld prepare that one as well.

      Yes, you are right. There will be some query/syntax not written in best method since I'm still learning this.

      Any recommendations?

        Just prepare it the same way you did the first one, that is, by using placeholders where any data will be provided by variables. Then pass the variables in the execute statement. This will define the variables as parameters and guarantee they will not be used as DDL, DML, or TCL, even if they include malicious values.

Re: Perl oracle insert error handling
by Anonymous Monk on Dec 23, 2014 at 16:33 UTC

    It looks like your problems are not so much with the logic but with syntax instead. If you know some Perl, you should probably start with cleaning that up to make your code runnable. Otherwise, start with perlintro and perlsyn.

Re: Perl oracle insert error handling
by Anonymous Monk on Dec 23, 2014 at 16:49 UTC
      Not intentionally left out that info but honestly didn't remember to put that. Since trying to sort out this issue for sometime now is really stressing me out.