Generally, placeholders can only hold the place of *values*, not structural elements like table and column names and subselect queries. You can (for most DBDs, I believe) use placeholders for values in a subquery so something like this might work:
$sth=$dbh->prepare("
UPDATE tableA
SET colA =( SELECT colB FROM tableB WHERE colC=? )
WHERE tableA.rec_no=?
");
foreach my $row ( @rows ) {
$sth->execute(
$row->{'tableB.value'}, $row->{'tableA.value'}
) or die $dbh->errstr;
}
Note that the order of the values in the execute is the order of the placeholders in the SQL, not the order the tables are opened.