Perl's DBI, available on the CPAN, supports parameterized SQL calls. Both the do method and prepare method support parameters ("placeholders", as they call them) for most database drivers. For example:

$sth = $dbh->prepare("SELECT * FROM users WHERE email = ?");
foreach my $email (@emails) {
    $row = $sth->fetchrow_hashref;

However, you can't use parameterization for identifiers (table names, column names) so you need to use DBI's quote_identifier() method for that:

# Make sure a table name we want to use is safe:
my $quoted_table_name = $dbh->quote_identifier($table_name);

# Assume @cols contains a list of column names you need to fetch:
my $cols = join ',', map { $dbh->quote_identifier($_) } @cols;

my $sth = $dbh->prepare("SELECT $cols FROM $quoted_table_name ...");

You could also avoid writing SQL by hand by using DBIx::Class, SQL::Abstract etc to generate your SQL for you programmatically.

What is Taint mode?

Taint mode is a special set of security checks that Perl performs on data input into your program from external sources. The input data is marked as tainted (untrusted) and may not be used in commands that would allow you to shoot yourself in the foot. See the perlsec manpage for a detailed breakdown of what taint mode tracks.

To invoke taint mode:

# From the command line
perl -T

# At the top of your script
#!/usr/bin/perl -T

When your script trips one of the taint checks your application will issue a fatal error message. For testing purposes -t will issue warnings instead of fatal errors. -t is not a substitute for -T.

To do

Explain how DBI supports taint mode, both inbound and outbound.