+ All Categories
Home > Documents > Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Date post: 06-Jan-2018
Category:
Upload: bruno-stanley
View: 224 times
Download: 1 times
Share this document with a friend
Description:
Using Perl & DBI/DBD::Informix 3 Why Perl? Easy To Start Many Modules Available Autovivification Garbage Collection Text Manipulation & Regular Expressions Portability Easy Access And Interaction With System Commands Hashes CGI Speed Code Reusability Using Modules
50
Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP [email protected]
Transcript
Page 1: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl and DBI/DBD With Informix Databases

Darryl PriestPiper Rudnick LLP

[email protected]

Page 2: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 2

Agenda

• What is DBI & DBD::Informix?• Why Perl?• Why DBI/DBD::Informix?• Perl Basics• Database Connections• Static SQLs• Fetching Data• Other SQLs (Inserts, Deletes, etc.)• Putting It All Together• Supported, But Not Covered

Page 3: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 3

Why Perl?

• Easy To Start• Many Modules Available• Autovivification • Garbage Collection• Text Manipulation & Regular Expressions• Portability• Easy Access And Interaction With System Commands• Hashes• CGI • Speed• Code Reusability Using Modules

Page 4: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 4

Why DBI/DBD::Informix?

• Very well tested• Data Fetch Method Choices• IBM/Informix Support• Portability• Database Connections

Page 5: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 5

Perl Basics

• #!/usr/bin/perl -w • Variable Types (scalars, arrays, hashes, references)• use DBI;• use strict;• Variable Scope• TMTOWTDI• q# and qq#

Page 6: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 6

DBI Generalizations

• Database connections are referred to as database handles usually named $dbh, etc.

• Select SQLs usually follow the patternprepare,

execute, fetch, fetch, fetch …execute, fetch, fetch, fetch …

• Non-select SQLs usually follow the patternprepare,

execute, execute,

Page 7: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 7

Database Connections$dbh = DBI->connect($data_source, $username, $auth, \%attr);

$dbh = DBI->connect(“DBI:Informix:$database");

$dbh = DBI->connect(“DBI:Informix:$database", '', '', { AutoCommit => 0, PrintError => 1 });

my $dbh = DBI->connect("DBI:Informix:MyDatabase") or die "MyDatabase Database Open Error: $DBI::errstr\n";$dbh->{ChopBlanks} = 1;$dbh->{AutoCommit} = 1;$dbh->{PrintError} = 1;$dbh->{RaiseError} = 1;

my $ps_dbh = DBI->connect("DBI:Informix:hrdb\@remote_tcp") or die "PeopleSoft Database Open Error: $DBI::errstr\n";

$dbh->disconnect();

Page 8: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 8

Static SQLs$el_dbh->do("set isolation to dirty read;");$el_dbh->do("set lock mode to wait;");

$sql = qq#create temp table temp_teamleader (tkinit char(5), teamleader char(5) ) with no log in tempdbs;#;$el_dbh->do($sql);

$sql = qq#insert into temp_teamleader(tkinit, teamleader) select udjoin, udvalue from udf where udf.udtype = "TK" and udf.udfindex = 55;#;

my $ins_teamleader_sth = $el_dbh->prepare($sql);$ins_teamleader_sth->execute();$el_dbh->do("create index teamldr_idx1 on temp_teamleader(tkinit);");$el_dbh->do("update statistics high for table temp_teamleader;");

Page 9: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 9

Fetching Data (Static SQL)$sql = qq#select rttype, rtdesc from crltype order by 1;#;

my $get_party_type_sth = $el_dbh->prepare($sql);

$get_party_type_sth->execute();

Page 10: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 10

Fetching Data with Placeholders$sql = qq#select emplid, primary_contact, contact_name, relationship, phone from ps_emergency_cntct where emplid = ? order by primary_contact desc, contact_name;#;

my $get_emerg_contact_sth = $ps_dbh->prepare_cached($sql);

$get_emerg_contact_sth->execute(“12345”);

• Or even better, using a scalar variablemy $InEmplid = “12345”;$get_emerg_contact_sth->execute($InEmplid);

Page 11: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 11

Processing Fetched Data$sql = qq#select rttype, rtdesc from crltype order by 1;#;

my $get_party_type_sth = $el_dbh->prepare($sql);$get_party_type_sth->execute();

my (@Row, $PartyTypes);while ( @Row = $get_party_type_sth->fetchrow_array() ) { $PartyTypes{$Row[0]} = $Row[1];}

• Same thing using hash referencesmy ($Row, %PartyTypes);while ( $Row = $get_party_type_sth->fetchrow_hashref() ) { $PartyTypes{$Row->{rttype}} = $Row->{rtdesc};}

Page 12: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 12

Processing Fetched Data, continued$sql = qq#select count(*), sum(lamount) from ledger where linvoice = ? and lzero != "Y";#;

my $check_sth = $dbh->prepare($sql);$check_sth->execute($InvoiceNumber);

($NotPaid, $Amount) = $check_sth->fetchrow_array();

if ( $NotPaid > 0 ) { print "Not Paid, $NotPaid Ledger Items"; } else { print "Paid, Moving ...";}

Page 13: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 13

Processing Fetched Data, continued$sql = qq#select fieldname, fieldvalue, xlatlongname, xlatshortname from xlattable x where effdt = ((select max(effdt) from xlattable x1 where x1.fieldname = x.fieldname and x1.fieldvalue = x.fieldvalue and x1.effdt <= TODAY and x1.language_cd = "ENG")) and x.fieldname in ("COMP_FREQUENCY", "EMPL_TYPE", "REG_TEMP", "ACTION", "MILITARY_STATUS", "ETHNIC_GROUP", "REFERRAL_SOURCE", "FULL_PART_TIME", "OFFICER_CD", "FLSA_STATUS","SEX", "MAR_STATUS", "EMPL_STATUS", "HIGHEST_EDUC_LVL", "PHONE_TYPE") and x.language_cd = "ENG" order by 1,2;#;

my $get_xlat_sth = $ps_dbh->prepare($sql);$get_xlat_sth->execute();

my ($XlatRow);while ($XlatRow = $get_xlat_sth->fetchrow_hashref()) { $Xlat{ $XlatRow->{fieldname} } { $XlatRow->{fieldvalue} } = { longname => $XlatRow->{xlatlongname}, shortname => $XlatRow->{xlatshortname} };}

Page 14: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 14

Processing Fetched Data, continued

• Previous example loads the %Xlat hash with values such as:– $Xlat{MAR_STATUS}->{A}->{longname} = “Head of Household”– $Xlat{MAR_STATUS}->{A}->{shortname} = “Hd Hsehld”– $Xlat{MAR_STATUS}->{M}->{longname} = “Married”;– $Xlat{MAR_STATUS}->{M}->{shortname} = “Married”;– $Xlat{SEX}->{F}->{longname} = “Female”;– $Xlat{SEX}->{M}->{shortname} = “Male”;

• Hash values are referenced with:– $Xlat{SEX}->{ $Active->{sex} }->{shortname}– $Xlat{MAR_STATUS}->{ $Active->{mar_status} }->{longname}

Page 15: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 15

Binding Columns To Fetch Data$sql = qq#select pcode, pdesc from praccode where pdesc is not null order by 1;#;

my $get_praccodes_sth = $el_dbh->prepare($sql);

$get_praccodes_sth->execute();

my ($b_pcode, $b_pdesc);$get_praccodes_sth->bind_columns(undef, \$b_pcode, \$b_pdesc);

while ( $get_praccodes_sth->fetch ) { $PracCodes{$b_pcode} = $b_pdesc;}

Page 16: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 16

Binding Columns Continued$sql = qq#select cmatter, to_char(cdisbdt, '%m/%d/%Y') cdisbdt, cbillamt from cost where cmatter is not null;#;

my $get_cost_sth = $el_dbh->prepare($sql);my (%CostRow);$get_cost_sth->bind_columns(undef, \$CostRow{cmatter}, \$CostRow{cdisbdt}, \$CostRow{cbillamt});

while ( $get_cost_sth->fetch() ) { … Do Something With %CostRow Hash Values …}

Alternate syntax$sth->bind_col($col_num, \$col_variable);$sth->bind_columns(@list_of_refs_to_vars_to_bind);

Page 17: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 17

Preparing & Fetching Together

my $sql = qq#select emplid, name_first2last name from pm_employees_v#;

my $NamesRef = $dbh->selectall_hashref($sql, "emplid");

…….

while ( $PeopleRow = $get_people_with_subitem_sth->fetchrow_hashref() ) {

…………

if ( defined $NamesRef->{ $PeopleRow->{emplid} } ) { print "- $NamesRef->{ $PeopleRow->{emplid} }{name} "; } else { print “- Unknown”; }}

Page 18: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 18

Inserting Rows

• Declare The Insert Statement Handle$sql = qq#insert into winoutstat(wouser, wouser1, woreport, wotitle, wofile, wodate0, wotime0, wostat1, wopid) values(?, ?, ?, ?, ?, ?, ?, ?, ?);#;

my $ins_win_sth = $el_dbh->prepare_cached($sql);

• Insert The Row$ins_win_sth->execute($Logon, $Logon, "Reminders", $Title, $FileName, $OutDate, $OutTime, "RUNNING", $$);

my @Errd = @{$ins_win_sth->{ix_sqlerrd}};$Hold{woindex} = $Errd[1];

Alternate syntax$Hold{woindex} = $ins_win_sth->{ix_sqlerrd}[1];

Page 19: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 19

Deleting Data

• Declare The Delete Statement Handle$sql = qq#delete from pm_reminders where matter_num = ? and location = ? and run_date = TODAY and run_by = ?;#;

my $del_remind_sth = $el_dbh->prepare($sql);

• Delete Row(s) Based On Passed Parameters$del_remind_sth->execute($MatRow->{mmatter}, $Hold{location}, $ThisLogon);

Page 20: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 20

Using DBI With CGIsub show_elite_files {

print header(), start_html(-title=>"User File Manager", -style=>{'src'=>'/styles/inSite_Style.css'});

$sql = qq#select woindex, woreport, wotitle, wodate0, wotime0, wodate1, wotime1, wodesc1 from winoutstat where (wostat1 = "COMPLETE" or wostat2 = "COMPLETE") and wouser = ? order by wodate0 desc, wotime0;#;

my $get_files_sth = $el_dbh->prepare($sql);$get_files_sth->execute($ThisLogon);

my ($FileRow, $ViewLink, $ShowDate, $Count);$Count = 0;while ( $FileRow = $get_files_sth->fetchrow_hashref() ) { $ViewLink = a({-href=>“getfiles.cgi?Session=${InSession}&FileNum=$FileRow->{woindex}"}, "Archive");

$ShowDate = "$FileRow->{wodate0} $FileRow->{wotime0}"; if ( $FileRow->{wodate0} ne $FileRow->{wodate1} ) { $ShowDate .= " - " . $FileRow->{wodate1} . " " . $FileRow->{wotime1}; } elsif ( $FileRow->{wotime0} ne $FileRow->{wotime1} ) { $ShowDate .= "-" . $FileRow->{wotime1}; }

Page 21: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 21

Using DBI With CGI, continued ### If This Is The First File Printed, Print The Headers First if ( $Count == 0 ) { my $ThisName = get_user_name($ThisLogon); print start_table({-width=>'100%%', -border=>1, -cellpadding=>'5'}), $NewLine, Tr ( th ({-colspan=>'5'}, h4("Elite Report Files For User $ThisName") ) ), Tr ( th ( "&nbsp" ), th ( h4("Report") ), th ( h4("Title") ), th ( h4("Report Date") ), th ( h4("Report Description") ) ); } ### Print Information For This File print Tr ( td ({-align=>'center'}, "$ViewLink"), td ({-align=>'left'}, "$FileRow->{woreport}"), td ({-align=>'left'}, "$FileRow->{wotitle}"), td ({-align=>'center'}, "$ShowDate"), td ({-align=>'left'}, "$FileRow->{wodesc1}") );

$Count++;}

Page 22: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 22

Using DBI With CGI, continued### If No File Rows Found Show Error & Back Button, Otherwise### Print The End Of The Tableif ( $Count == 0 ) { print br, br, textfield(-name=>'ProcessMessage', -size=>'80', -style=>$ErrorStyle, -maxlength=>'80', -value=>"No Files Were Found In Your Elite File Manager!"), br, br; print_back(); return; } else { print end_table(); }

print end_html();

} ### End Of SubRoutine show_elite_files

Page 23: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 23

Using DBI With CGI, continued

Page 24: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 24

Defining Reusable Code#!/usr/bin/perlpackage MyLib;use strict;require Exporter;use vars qw($VERSION @ISA @EXPORT);$VERSION = 0.01;@ISA = qw(Exporter);@EXPORT = qw(get_names);

sub get_names {my ($UseDbh, $Emplid) = @_;my (@RetVals);my $sql = qq#select first_name, last_name from pm_employees_v where emplid_s = ?;#;

my $get_names_sth = $UseDbh->prepare_cached($sql);$get_names_sth->execute($Emplid);

@RetVals = $get_names_sth->fetchrow_array();return @RetVals;}

1;

Page 25: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 25

Using Your Module#!/usr/bin/perl –wuse DBI;use strict;

use lib q{/perl/modules/};use MyLib;

…………

if ( defined $Emplid ) { my (@RetNames) = MyLib::get_names($dbh, $Emplid); if ( defined $RetNames[0] ) { $Name = $RetNames[0]; } else { $Name = “Name Unknown”; }}

Page 26: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 26

Default Database Connection Modulesub default_db_connect {

my ($DB, $Server) = @_;

my ($dbh);if ( defined $Server and length($Server) > 1 ) { $dbh = DBI->connect("DBI:Informix:${DB}\@${Server}"); } else { $dbh = DBI->connect("DBI:Informix:${DB}", undef, undef,{ PrintError=>0, RaiseError=>0 }); if ( ! defined $dbh ) { $Server = default_informix_tcp(); ### Change Informix Server Name s/_shm/_tcp/ $dbh = DBI->connect("DBI:Informix:${DB}\@${Server}"); }}if ( defined $dbh ) { $dbh->{AutoCommit} = 1; $dbh->{ChopBlanks} = 1; $dbh->{PrintError} = 1; $dbh->{RaiseError} = 1; if ( $dbh->{ix_LoggedDatabase} ) { $dbh->do("set lock mode to wait;"); } if ( $dbh->{ix_ModeAnsiDatabase} ) { $dbh->do("set isolation to dirty read;"); } return $dbh; } else { die "$DB Database Open Error, Error: $DBI::errstr"; }} ### End Of SubRoutine default_db_connect

Page 27: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 27

Get Employee Data Example#!/usr/bin/perl -w$| =1;use DBI;use strict;use Getopt::Std;

use lib q{/perl/modules/bin};use Defaults;

my $Usage = qq#Usage: empl_info.pl [ -c Columns -d Database ] -e Emplid -l Logon -n Name

-c Column Name Match To Be Reported -d Database Server To Select Database Data From -e Employee ID To Report -l Employee Logon ID To Report -n Employee Name To Report

#;

use vars qw($opt_c $opt_d $opt_e $opt_l $opt_n);getopts('c:d:e:l:n:');

Page 28: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 28

Get Employee Data Example, cont’d### Get User Input, Make Sure To Get An Emplid, Name Or Logonmy (%In);if ( defined $opt_c ) { $In{columns} = $opt_c; }

if ( defined $opt_d ) { $In{db} = "MyDatabase\@$opt_d"; } else { $In{db} = "MyDatabase"; }

if ( defined $opt_e ) { $In{emplid} = $opt_e; }

if ( defined $opt_l ) { $In{logon} = $opt_l; $In{logon} =~ tr/A-Z/a-z/;}if ( defined $opt_n ) { $In{name} = $opt_n; if ( $In{name} !~ /\*/ ) { $In{name} = "*" . $In{name} . "*"; }}if ( ! exists $In{emplid} and ! exists $In{logon} and ! exists $In{name} ) { die "\n$Usage\n\n";}

### Connect To MyDatabasemy ($dbh);if ( defined $opt_d ) { $dbh = default_db_connect("MyDatabase", $opt_d); } else { $dbh = default_db_connect("MyDatabase"); }

Page 29: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 29

Get Employee Data Example, cont’d### Select Emplid & Name For Passed Emplid/Logon/Name Matchmy $sql = qq#select emplid, name_first2last from empl_search where#;

my ($get_emplid_sth);SWITCH: { if ( exists $In{emplid} ) { $sql .= qq# emplid = ?#; $get_emplid_sth = $dbh->prepare($sql); $get_emplid_sth->execute($In{emplid}); last SWITCH; } if ( exists $In{logon} ) { $sql .= qq# lower(logon_id) matches ?#; $get_emplid_sth = $dbh->prepare($sql); $get_emplid_sth->execute($In{logon}); last SWITCH; } if ( exists $In{name} ) { $sql .= qq# name_first2last matches ?#; $get_emplid_sth = $dbh->prepare($sql); $get_emplid_sth->execute($In{name}); last SWITCH; }}

Page 30: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 30

Get Employee Data Example, cont’d### Fetch All Employees Found For Passed Matchmy $EmplidRef = $get_emplid_sth->fetchall_arrayref();

### If Only Employee Matches, Call Show Subroutine, Else ### Show List Of Matching Employees And Allow User To Select### In A Loop From The List And Reportif ( @{$EmplidRef} > 0 ) { if ( @{$EmplidRef} == 1 ) { list_info($EmplidRef->[0][0]); } else { show_list($EmplidRef); my ($Choice); while (<>) { chomp;

if ( $_ =~ /[Xx]/ ) { last; }

$Choice = $_ - 1; list_info($EmplidRef->[$Choice][0]); show_list($EmplidRef); } } } else { print "\n\nNo Matches Found For Passed Criteria\n\n";}$dbh->disconnect();

Page 31: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 31

Get Employee Data Example, cont’d### SubRoutine: show_list### This subroutine will list the passed list reference### of employee ids and names.

sub show_list {my ($ListRef) = @_;

my ($x, $y);print "\n\n Selected Employees\n";print " -------- ---------\n";for ($x = 0; $x < @{$ListRef}; $x++) { $y = $x + 1; print " $y.) $ListRef->[$x][1]($ListRef->[$x][0])\n";}print "\nEnter Choice(or x to exit): ";

} ### End Of SubRoutine show_list

Page 32: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 32

Get Employee Data Example, cont’d### SubRoutine: list_info### This subroutine will list the employee information### from pm_employees_v for the passed emplid.sub list_info {

my ($ThisEmplid) = @_;

### Select All Potential Data Columns For Passed Emplid$sql = qq#select * from employees_v where emplid = ?#;

my $get_MyDatabase_sth = $dbh->prepare_cached($sql);

$get_MyDatabase_sth->execute($ThisEmplid);

my ($Row, $Var);while ( $Row = $get_MyDatabase_sth->fetchrow_hashref() ) { ### Print "Header" Of Employee Information print ">" x 78, "\n"; for $Var ( qw(emplid name_first2last location_desc long_jobtitle) ) { printf(" %18s: %-50s\n", $Var, $Row->{$Var}); } print "\n";

Page 33: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 33

Get Employee Data Example, cont’d ### For Each Returned Column for $Var ( sort keys %{$Row} ) { if ( $Var =~ /_s$/ ) { next; }

### If User Selected Specific Columns To Report, Only ### Report The Selected Columns if ( exists $In{columns} ) { if ( $Var !~ /$In{columns}/ ) { next; } }

### If This Column Contains Data, Report It if ( defined $Row->{$Var} and length($Row->{$Var}) > 0 ) { write; } } print "<" x 78, "\n";}

### Define Output Format For Employee Dataformat STDOUT = @>>>>>>>>>>>>>>>>>: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Var, $Row->{$Var}~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

$Row->{$Var}.} ### End Of SubRoutine list_info

Page 34: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 34

Get Employee Data Example, cont’dempl_info.pl -n Darryl -c "job|name"

Selected Employees -------- --------- 1.) Darryl Priest(xxx) 2.) Darryl Someone Else(xxx)

Enter Choice(or x to exit): 1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> emplid: xxx name_first2last: Darryl Priest location_desc: Baltimore Office long_jobtitle: Analyst / Developer Lead

deptname: IT Application Services first_name: Darryl job_family: MIS last_name: Priest long_deptname: IT Application Services long_jobtitle: Analyst / Developer Lead name_first2last: Darryl Priest name_last2first: Priest, Darryl short_name: D. Priest<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Selected Employees -------- --------- 1.) Darryl Priest(xxx) 2.) Darryl Someone Else(xxx)

Enter Choice(or x to exit): x

Page 35: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 35

Archive Data Example#!/usr/local/bin/perl$| =1;use DBI;use Getopt::Std;

use lib q{/perl/modules/bin};use GenLib qw(commify_integer);

use vars qw($opt_a $opt_c $opt_d $opt_k $opt_o $opt_s $opt_t $opt_v $opt_w $opt_u $opt_x);

my $Usage = qq#

Usage:$0 [ -d Database -t Table ]

[< -k File Split Column Key >] [< -c Column -o Operator -v Threshold Value >] [< -s Output Directory -a Append Existing Files >]

[< -w Where -u Save Deletes -x Experimental Delete >]

-d Database Name -t Database Table To Be Archived -k Key Column Used To Split Output Files -c Column Name To Key Archive Selection -o Operator To Determine Which Data To Keep -v Threshold Value For The Key Column -a Append To Existing Output Files -s Directory To Save The Archived Data -w Optional Additional Where Clause -u Save Deleted Rows In Unload Type Files -x Experimental, Don't Actually Delete, Just Count

#;

Page 36: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 36

Archive Data Example, cont’d### Define Usage Variables And Get From Passed Optionsmy ($Append, $Column, $Database, $SplitKey, $Operator, $Table);my ($Threshold, $Where, $Directory, $Delete, $Write);

getopts('ac:d:k:o:s:t:v:w:ux');

### Make Sure The Table And Database Are Passedif ( defined $opt_d ) { $Database = $opt_d; } else { print $Usage; exit; }

if ( defined $opt_t ) { $Table = $opt_t; } else { print $Usage; exit; }

### Get Optional Where Clauseif ( defined $opt_w ) { $Where = $opt_w; }

### Get Optional Save Deletes Optionif ( defined $opt_u ) { $Write = 1; } else { $Write = 0; }

### Get Output File Split Keyif ( defined $opt_k ) { $SplitKey = $opt_k; }

### If Column Selection Criteria Is Passed, Make Sure The ### Correct Pieces Have All Been Passedif ( defined $opt_c ) { $Column = $opt_c; }

if ( defined $opt_o ) { $Operator = $opt_o; } elsif ( defined $Column ) { $Operator = "="; }

Page 37: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 37

Archive Data Example, cont’dif ( defined $opt_v ) { $Threshold = $opt_v; ### If The Threshold Has Non Digits, Quote It, Unless ### It's Already Been Quoted if ( $Threshold =~ /\D/ ) { if ( $Threshold !~ /[\"\']/ ) { $Threshold = qq#"$Threshold"#; } }}

### Get Optional Output Directoryif ( defined $opt_s ) { $Directory = $opt_s; $Write = 1; } else { $Directory = $Table; }

### Get Optional X Options, Doesn't Actually Delete Dataif ( defined $opt_x ) { $Delete = 0; } else { $Delete = 1; }

### Get Append Option, If Exists, Otherwise Default To Not Appendif ( defined $opt_a ) { $Append = 1; $Write = 1; } else { $Append = 0; }

### Display Passed Options Back To Userprint "\n\n", '>' x 60, "\n";

Page 38: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 38

Archive Data Example, cont’dprint "Preparing To Archive Data From ${Database}:${Table} ...\n";if ( $Write ) { print "Data Rows To Be Deleted Will Be Saved In Directory $Directory\n"; } else { print "Deleted Data Rows Will Not Be Written To Files\n"; }

if ( $Append ) { print "Existing Output Files Will Be Appended To\n"; }

### Build SQL To Select Data Rows To Be Archivedmy ($sql, $SC, $WC);

$SC = qq#select#;

if ( defined $SplitKey ) { print "Output Files Will Be Split By Key $SplitKey\n"; $SC .= qq# $SplitKey,#;}

$SC .= qq# rowid, * from $Table#;

if ( defined $Operator and defined $Threshold ) { print "Limiting Data Selection By $Column $Operator $Threshold\n"; $WC = qq#$Column $Operator $Threshold#;}

if ( defined $Where ) { print "Further Restricted By: $Where\n"; if ( defined $WC ) { $WC .= qq# and#; } $WC .= qq# $Where#;}

if ( defined $WC ) { $sql = qq#$SC where $WC#; } else { $sql = $SC; }

Page 39: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 39

Archive Data Example, cont’dprint "\nSelect Data Rows With SQL:\n$sql\n";

if ( ! $Delete ) { print "\nOnly Unloading Data, No Rows Will Be Deleted!!!\n"; }

### Verify Input Selections, If Running Interactivelyif ( -t STDIN and -t STDOUT ) { print "\nPress Any Key To Continue Or Control-C To Cancel\n"; my $Continue = getc();}

### Make Directory To Write The Archived Data Out Toif ( $Write ) { if ( ! -d $Directory ) { print "Creating Directory $Directory For Output Files At ", `date +'%D %r'`; mkdir ($Directory, 0777) or die "Error Creating Directory For Output $Directory, $!\n"; }}

### Open The Select Connection To The Databasemy $dbh = DBI->connect("DBI:Informix:$Database") or die "$Database Database Open Error: $DBI::errstr\n";$dbh->{ChopBlanks} = 1;$dbh->{AutoCommit} = 1;$dbh->{PrintError} = 1;$dbh->{RaiseError} = 1;

### Set The Database Lock Mode $dbh->do("set lock mode to wait 300");

Page 40: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 40

Archive Data Example, cont’d### Build Statement Handle To Select Rows To Be Deletedmy $select_sth = $dbh->prepare($sql);$select_sth->execute();

### Get Current Row Count From The Table$sql = qq#select count(*) from $Table#;my $count_sth = $dbh->prepare($sql);$count_sth->execute();my ($OrigCount) = $count_sth->fetchrow_array();print "\n\nBefore Deletions $Table Has ", commify_integer($OrigCount), " Rows\n";

### Get Current Max Rowid From The Table$sql = qq#select max(rowid) from $Table#;my ($OrigMaxRowId) = $dbh->selectrow_array($sql);print "Max RowId In $Table Is ", commify_integer($OrigMaxRowId), " \n\n";

### Prepare Delete Handle, Deleting By Rowid$sql = qq#delete from $Table where rowid = ?#;my $del_sth = $dbh->prepare($sql);

### Process Rows To Be Deleted Writing To Key Driven Output### Files And Save The Rowids To Delete Latermy (@DataRow, $KeyValue, $RowId, %Files, $FileHandle, $NewFile);my $DelRows = 0;while ( @DataRow = $select_sth->fetchrow_array() ) { if ( $DelRows > 0 and ( $DelRows % 10000 ) == 0 ) { print commify_integer($DelRows), " Rows Read For Delete At ", `date +'%D %r'`; }

Page 41: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 41

Archive Data Example, cont’d ### If Archiving Using A Column Get That Column From The Results, Otherwise Use ### Set To A Default Values, Also Get The Rowid From The Fetch Array if ( defined $SplitKey ) { $KeyValue = shift(@DataRow); } else { $KeyValue = "all"; }

$RowId = shift(@DataRow);

### If The Key Data Column Is Not Defined Skip The Row if ( ! defined $KeyValue ) { next; }

### If This Key Has Not Been Processed Yet, Open A New ### Output File For This Key if ( ! defined $Files{$KeyValue}{Key} ) { $Files{$KeyValue}{Key} = $KeyValue; $Files{$KeyValue}{FileName} = "${Directory}/${Table}_${KeyValue}.unl";

### If Deleted Rows Are To Be Written, Check For Existing ### Files, And Open The Appropriate File Handle if ( $Write ) { ### If The File Already Exists & We're Not Appending ### Move The Old File To A .old File if ( -f $Files{$KeyValue}{FileName} ) { $NewFile = "$Files{$KeyValue}{FileName}.old"; if ( ! $Append ) { rename $Files{$KeyValue}{FileName}, $NewFile; } }

### Open The New File $Files{$KeyValue}{Handle} = $KeyValue; open ($Files{$KeyValue}{Handle}, ">> $Files{$KeyValue}{FileName}") or die "Error Opening $Files{$KeyValue}{FileName}, $!\n"; } }

Page 42: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 42

Archive Data Example, cont’d ### If Deletes Are Being Saved, Clean Up The Data & Write It To The Correct File if ( $Write ) { ### Convert NULLs Into Empty Strings map { $_ = "" unless defined $_ } @DataRow;

### Write This Row To The Appropriate File, If Deletes Are Being Saved $FileHandle = $Files{$KeyValue}{Handle}; print $FileHandle join('|', @DataRow), "|\n"; } $Files{$KeyValue}{Count}++;

### Actually Delete The Row if ( $Delete ) { $del_sth->execute($RowId); }

$DelRows++;}print "\nProcessed ", commify_integer($DelRows), " Rows From $Table At ", `date +'%D %r'`;

### Close All Output Filesmy ($x);print "\n";if ( $Write ) { print "Closing Output Files At ", `date +'%D %r'`; }foreach $x ( sort keys %Files ) { if ( $x ne "all" ) { print "Found ", commify_integer($Files{$x}{Count}), " Rows For $SplitKey = $x\n"; } if ( $Write ) { $FileHandle = $Files{$x}{Handle}; close $FileHandle; }}

Page 43: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 43

Archive Data Example, cont’d### Recheck The Row Count From The Table$count_sth->execute();my ($NewCount) = $count_sth->fetchrow_array();print "\nThe Table $Table Now Has ", commify_integer($NewCount), " Rows\n";

### Check For Rows With RowIds Greater Than The Max From When The Program Started$sql = qq#select count(*) from $Table where rowid > $OrigMaxRowId#;my ($NewRows) = $dbh->selectrow_array($sql);print "Found ", commify_integer($NewRows), " With RowIds > ", commify_integer($OrigMaxRowId), "\n";

### Display Warnings If Row Count Or Row Id Checks Failif ( $Delete ) { if ( ( $OrigCount - $DelRows != $NewCount ) or $NewRows > 0 ) { print "\n\n", '!' x 60, "\n"; print "Potential Deletion Problems\n"; print "Table $Table Had ", commify_integer($OrigCount), " Rows, ", commify_integer($DelRows), " Were To Be Deleted, But Count Is ", commify_integer($NewCount), "\n"; print "Found ", commify_integer($NewRows), " With RowIds > ", commify_integer($OrigMaxRowId), "\n"; print '!' x 60, "\n"; } else { print "Appears To Have Processed Correctly\n"; }}### Disconnect From Databases$dbh->disconnect();

print "\n", '>' x 60, "\n";print "Finished Archiving ${Database}:${Table} At ", `date +'%D %r'`;

Page 44: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 44

Archive Data Example, cont’darchive_data.pl -d mydb -t testtable -k "year(date1)" -x -u

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Preparing To Archive Data From mydb:testtable ...Data Rows To Be Deleted Will Be Saved In Directory testtableOutput Files Will Be Split By Key year(date1)

Select Data Rows With SQL:select year(date1), rowid, * from testtable

Only Unloading Data, No Rows Will Be Deleted!!!

Press Any Key To Continue Or Control-C To Cancel

Creating Directory testtable For Output Files At 04/20/04 03:07:14 PM

Before Deletions testtable Has 6 RowsMax RowId In testtable Is 262

Processed 6 Rows From testtable At 04/20/04 03:07:14 PM

Closing Output Files At 04/20/04 03:07:14 PMFound 2 Rows For year(date1) = 2000Found 2 Rows For year(date1) = 2001Found 2 Rows For year(date1) = 2002

The Table testtable Now Has 6 RowsFound 0 With RowIds > 262>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Finished Archiving mydb:testtable At 04/20/04 03:07:14 PM

wc -l testtable/* 2 testtable/testtable_2000.unl 2 testtable/testtable_2001.unl 2 testtable/testtable_2002.unl

Page 45: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 45

Archive Data Example, cont’darchive_data.pl -d son_db -t precost -c pcdate -o '<' -v '"01/01/2002"' -w 'pcvalid = "P"‘

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Preparing To Archive Data From son_db:precost ...Deleted Data Rows Will Not Be Written To FilesLimiting Data Selection By pcdate < "01/01/2002"Further Restricted By: pcvalid = "P"

Select Data Rows With SQL:select rowid, * from precost where pcdate < "01/01/2002" and pcvalid = "P"

Before Deletions precost Has 11,355,500 RowsMax RowId In precost Is 206,197,776

10,000 Rows Read For Delete At 01/14/04 06:06:59 PM20,000 Rows Read For Delete At 01/14/04 06:07:24 PM………..7,730,000 Rows Read For Delete At 01/14/04 10:06:16 PM7,740,000 Rows Read For Delete At 01/14/04 10:07:47 PM

Processed 7,747,585 Rows From precost At 01/14/04 10:10:02 PM

The Table precost Now Has 3,607,915 RowsFound 0 With RowIds > 206,197,776Appears To Have Processed Correctly

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Finished Archiving son_db:precost At 01/14/04 10:10:02 PM

Page 46: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 46

Archive Data Example, cont’darchive_data.pl -d son_db -t fmsaudit -c audate -o '<' -v '01/01/2002‘

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Preparing To Archive Data From son_db:fmsaudit ...Deleted Data Rows Will Not Be Written To FilesLimiting Data Selection By audate < "01/01/2002"

Select Data Rows With SQL:select rowid, * from fmsaudit where audate < "01/01/2002"

Before Deletions fmsaudit Has 4,597,692 RowsMax RowId In fmsaudit Is 93,006,083

10,000 Rows Read For Delete At 01/12/04 05:28:51 PM20,000 Rows Read For Delete At 01/12/04 05:29:05 PM………2,930,000 Rows Read For Delete At 01/12/04 06:22:47 PM2,940,000 Rows Read For Delete At 01/12/04 06:22:59 PM

Processed 2,943,968 Rows From fmsaudit At 01/12/04 06:23:03 PM

The Table fmsaudit Now Has 1,653,735 RowsFound 11 With RowIds > 93,006,083

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Potential Deletion ProblemsTable fmsaudit Had 4,597,692 Rows, 2,943,968 Were To Be Deleted, But Count Is 1,653,735Found 11 With RowIds > 93,006,083!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Finished Archiving son_db:fmsaudit At 01/12/04 06:23:03 PM

Page 47: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 47

Supported, But Not Covered In Detail

• Accessing The Informix SQLCA Values– $sqlcode = $sth->{ix_sqlcode};– $sqlerrm = $sth->{ix_sqlerrm};– $sqlerrp = $sth->{ix_sqlerrp};– @sqlerrd = @{$sth->{ix_sqlerrd}};– @sqlwarn = @{$sth->{ix_sqlwarn}};

• Transactions using $dbh->commit(); and $dbh->rollback();• Do With Parameters

– $dbh->do($stmt, undef, @parameters);– $dbh->do($stmt, undef, $param1, $param2);

• $dbh->quote($string)• $sth->finish and undef $sth• Blob fields

Page 48: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 48

Supported, But Not Covered, continued

• $sth attributes, NUM_OF_FIELDS, NAME, etc.• DBI->trace($level, $tracefile);• Fetch methods selectrow_array() & selectall_array()• $dbh->func()• Statement Handles For Update $st1 = $dbh->prepare("SELECT * FROM SomeTable FOR UPDATE"); $wc = "WHERE CURRENT OF $st1->{CursorName}"; $st2 = $dbh->prepare("UPDATE SomeTable SET SomeColumn = ? $wc"); $st1->execute; $row = $st1->fetch; $st2->execute("New Value");

• $sth->rows();

Page 49: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 49

Additional Information

• dbi.perl.org/ - DBI Home Page• www.perl.com - Perl• www.perl.org• www.cpan.org/ - Comprehensive Perl Archive Network• www.activestate.com

• perldoc DBI – DBI Man Pages• perldoc DBD::Informix – DBD::Informix Man Pages

• Programming Perl by Larry Wall, Tom Christiansen & Randal Schwartz • Programming the Perl DBI, by Alligator Descartes and Tim Bunce • Learning Perl by Randal Schwartz

Page 50: Using Perl and DBI/DBD With Informix Databases Darryl Priest Piper Rudnick LLP

Using Perl & DBI/DBD::Informix 50

Thanks!

• To the authors who brought us:– Perl

• Larry Wall

– DBI• Tim Bunce• Alligator Descartes

– DBD::Informix• Jonathan Leffler


Recommended