I believe it is a scoping problem. That is, the connection is destroyed when connectdb goes out of scope even though you pass the value of $dbhi back to the calling routine.
I've never tried this but you might try returning a reference to $dbhi (return \$dbhi). That might preserve the connection following the end of sub.
Update: OK, this was a bad suggestion. It doesn't work. The suggestion below, however does work.
What I usually do, though, is pass connectdb a reference to my db handle and assign the connection to that reference. Just replace $dbhi with $$dbhi in your subroutine.
Update: Here is some code for the above suggestion.
#calling function
# $cfg is a scalar that will hold a reference to a hash
# OpenODBC is a generic routine to establish an ODBC connection
# via Win32::ODBC
$rtncd = InitParams(\$cfg,\$db01);
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# database connections
# connection 1
# open database connections
($rtncd, $$db01) = OpenODBC($$cfg->{obtsdsn},$$cfg->{dbf01});
if($rtncd){
$$cfg->{logstr} =
"$$cfg->{county};$$cfg->{procdte};$$cfg->{fname};".
"$$cfg->{module};1;error;[]ODBC error, ($rtncd) ";
$$cfg->{logstr} .= ($rtncd == 2)
? "Could not connect with database $$cfg->{dbf01};"
: "Could not establish connection via $$cfg->{obtsdsn};" ;
$$cfg->{logstr} .= "ODBC;InitParams(); ; ; ";
UpdtMetaLog($$cfg->{logdir},$$cfg->{logfile},$$cfg->{logstr});
}
sub OpenODBC{
# Usage &OpenODBC([DSNNAME],[DatabaseName])
# opens a database connection using the basic ODBC driver
# returns 0 if connection established, 2 if connection fails,
# 3 if database not available
require Win32::ODBC;
my $dsn = $_[0];
my $dbf = 'USE '.$_[1];
my $uid = '***********';
my $pwd = '***********';
my $db = '';
my $rtncd = 0;
# Establish ODBC Connection
$rtncd = 2 unless($db = new Win32::ODBC("DSN=$dsn;UID=$uid;PWD=$pw
+d"));
# Establish the data base to use
$rtncd || ($db->Sql("$dbf") && ($rtncd = 3));
return ($rtncd,$db);
} # end OpenODBC()
PJ
unspoken but ever present -- use strict; use warnings; use diagnostics; (if needed)