You could build your update statment dynamically, and prepare it using prepare_cached. That way its only prepared once (for each variation), and you can still take good advantage of placeholders. This is not the tightest example, and is untested, but should serve its purpose:
my %col;
$col{foo}=1;
$col{bar}=undef;
my %vbph;
my @vbval;
foreach(sort keys %arg){
if(defined $arg{$_}){
$vbph{$_}='?';
push @vbval,$arg{$_};
}else{
$vbph{$_}='NULL';
}
}
my $sql='update baz set '.
join ', ',(map{$_.'='.$vb{$_}} sort keys %arg));
my $sth=$dbh->prepare_cached($sql);
$sth->execute(@vbval);