I have been working for weeks on trying to make a perl program work. Someone else wrote it and since then the data source has been changed. I have spent weeks searching line by line and doing tutorials. I am stuck. The code says @{ $Routings{$Code} }
which has a list of values [ $ProcessID, $Setup, $Process ]
but at the bottom of the code when foreach ( @{ $Routings{$Code} } ) {my $ProcessCodeID = @$_[0];}
it does not seem to be returning the data. If anyone could even help me print $ProcessCodeID
so I can track the data it would be extremely helpful.
Also if you could explain what @{$value{$key}}
represents that would really help too.
Thanks heaps.
%Routings = ();
my $dbh = DBI-> connect('dbi:ODBC:SQL')
or die "Couldn't open Databaxe: $DBI::errstr; stopped";
my $query= $dbh->prepare("SELECT Code, Setup, Process, ProcessID FROM ROUTING");
$query->execute() or die "Couldn't execute statement: $DBI::errstr; stopped";
while ( my ($Code, $setup, $process, $processid) = $query->fetchrow_array() ){
push ( @{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ] );
}
foreach ( @{ $Routings{$Code} } ) {
my $ProcessCodeID = @$_[0];
my $SetupMins = @$_[1];
my $ProcessMins = @$_[2];
}
First of all it is important that you use strict
and use warnings
at the start of your program, and declare all your variables at the point they are first used. This will cause Perl to generate some very useful messages that will reveal many simple errors that are easily overlooked.
As an example, you are assigning the variables $setup
, $process
, and $processid
but then pushing $Setup
, $Process
, and $ProcessID
onto an array. Perl identifiers are case-sensitive so these are three diffferent variables and will have a value of undef
at this point. use strict
would have printed a compilation error saying that $ProcessID
etc. hadn't been declared. (If you have a choice, it is better to use lower-case plus underscore for local identifiers like these. Seasoned Perl programmers will thank you.)
You should experiment with the Data::Dumper
module which will show the contents and structure of a complex nested Perl data structure like this. Once you have use Data::Dumper
in your program you can write
print Dumper \%Routings
which will show the contents of %Routings
as an anonymous hash.
The value of each element $Routings{$Code}
of the hash is a list (a reference to an array) of all the sets of ProcessID, Setup, and Process that correspond to that value of Code. (I presume the column Code
is non-unique, otherwise the data structure is more complex than it needs to be.) So the first set of three values for a given $Code
is at $Routings{$Code}[0]
and the ProcessID
for that set is $Routings{$Code}[0][0]
.
There is no code to assign a value to $Code
for the foreach
loop, and presumably you would want to loop over all the keys of the %Routings
hash.
Each time round the foreach
loop $_
is set to a reference to each triplet of values for the current $Code
. That means @$_
is a three-element array, but it should be indexed using $_->[0]
etc. instead of @$_[0]
which is a one-element array slice and poor coding practice. The code is made more obscure by using the default $_
here and I have clarified it below by using a named variable.
The code below fixes the problems I can see. Please come back if you need any further help.
use strict;
use warnings;
use DBI;
my %Routings;
my $dbh = DBI-> connect('dbi:ODBC:SQL')
or die "Couldn't open Databaxe: $DBI::errstr; stopped";
my $query= $dbh->prepare("SELECT Code, Setup, Process, ProcessID FROM ROUTING");
$query->execute or die "Couldn't execute statement: $DBI::errstr; stopped";
while ( my ($Code, $Setup, $Process, $ProcessID) = $query->fetchrow_array ){
push @{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ];
}
for my $Code (keys %Routings) {
foreach my $triplet ( @{ $Routings{$Code} } ) {
my $ProcessCodeID = $triplet->[0];
my $SetupMins = $triplet->[1];
my $ProcessMins = $triplet->[2];
print "$Code => ($ProcessCodeID, $SetupMins, $ProcessMins)\n";
}
}
Note that the assignments within the foreach
loop can be made clearer and more concise by performing them all at once. As I have explained, @$triplet
is a three-element array, so the equivalent assignment could be coded as simply
my ($ProcessCodeID, $SetupMins, $ProcessMins) = @$triplet;
(Please treat this code warily, as I cannot test it it thoroughly without significant work setting up a test database, although it does work correctly on a simple data set.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With