There are ways to avoid that unwanted clutter in your templates. I've only tested the
following with MySQL, but it's pretty slick. Try it out in a shell: ./foo.pl state=42
use DBI;
use CGI qw(param);
use Template;
my $dbh = DBI->connect( ... );
my $state_id = param('state');
my $states = $dbh->selectall_arrayref('
SELECT id,name,
IF (id = ?, 1, 0) AS selected
FROM state
',{Slice => {}}, $state_id);
my $tt = Template->new;
$tt->process(\*DATA, {states => $states}) || die $tt->error();
__DATA__
<select name="state">
<option value="">Pick A State, Any State</option>
[% FOREACH state = states %]
[% PROCESS option o = state %]
[% END %]
</select>
[% BLOCK option %]
<option value="[% o.id %]"
name="[% o.name %]"
selected="[% o.selected %]"
/>
[% END %]
But ... you are right. CGI.pm is very nice. By the way ... my point was TIMTOWTDI. That's all.