我正在为DBI更新编写子程序,并且在确定如何添加占位符和内容方面遇到一些麻烦......
我有这个:
sub row_update {
my $table = shift;
my %updates = @_;
my $placeholders = ...
$dbh->do("UPDATE $table SET (foo) WHERE (bar)") etc...
}
有什么想法吗?
我只想要一个简单的更新函数,我可以在其中发送x个参数(作为哈希)。
提前致谢!
答案 0 :(得分:4)
这样的事情可能足够好了:
sub update {
my ($dbh, $args) = @_;
my $table = $args->{table} || die 'need table';
my $updates = $args->{updates} || die 'need updates';
my @cols = keys %$updates;
my $query = 'UPDATE $table SET '.
(join ', ', map { '$_ = ?' } @cols)
($args->{where} ? ' WHERE '. $args->{where} : '');
my $sth = $dbh->prepare($query);
$sth->execute(map { $updates->{$_} } @cols);
return $sth;
}
使用它像:
my $sth = update $dbh, {
table => 'foo',
updates => {
col1 => 'new_value',
col2 => 'another_value',
},
where => 'id=42',
};
但是,你真的想要使用类似的ORM DBIx::Class。它可以更好地构建查询 像这样的字符串操作会。
(重写要参数化的where子句留给读者练习。你还需要引用更新密钥和表名。看看为什么人们使用ORM?)
编辑:考虑到这一点,您可能希望DBIx::Simple与SQL::Abstract结合使用。这将比ORM花费更少的配置工作,但仍然为您提供许多好处。
答案 1 :(得分:3)
如果我正确理解了这个问题,听起来好像是在SQL::Abstract之后。首先,我们创建一个SQL::Abstract
对象:
use SQL::Abstract;
my $sql = SQL::Abstract->new;
现在,作为一个例子,我们将使用它将一些数据插入表中:
my %record = (
FirstName => 'Buffy',
LastName => 'Summers',
Address => '1630 Revello Drive',
City => 'Sunnydale',
State => 'California',
Occupation => 'Student',
Health => 'Alive',
);
my ($stmt, @bind) = $sql->insert(’staff’,\%record);
这导致:
$stmt = "INSERT INTO staff
(FirstName, LastName, Address, City,
State, Occupation, Health)
VALUES (?, ?, ?, ?, ?, ?, ?)";
@bind = ('Buffy','Summers','1630 Revello Drive',
'Sunnydale',’California','Student','Alive');
关于这个的好处是我们可以直接将它传递给DBI:
$dbh->do($stmt, undef, @bind);
当然,您希望更新记录,而不仅仅是插入记录。幸运的是,这也很容易:
my $table = 'People';
my %new_fields = (
Occupation => 'Slayer',
Health => 'Dead',
);
my %where = (
FirstName => 'Buffy',
LastName => 'Summers',
);
my ($stmt, @bind) = $sql->update($table, \%new_fields, \%where);
$dbh->do($stmt, undef, @bind);
这会产生:
$stmt = 'UPDATE People SET Health = ?, Occupation = ?
WHERE ( FirstName = ? AND LastName = ? )';
@bind = ('Dead', 'Slayer', 'Buffy', 'Summers');
如果您要了解有关SQL::Abstract
的更多信息,建议您查看其CPAN page。在Perl Training Australia的使用Perl进行数据库编程手册中还有一章可以从course notes page免费获得。
一切顺利,
保
免责声明:我是Perl Training Australia的常务董事,因此我认为我们的课程笔记非常好。
答案 2 :(得分:1)
其他人建议通常“使用正确数量的”?“方法构建查询。
对于像这样的大多数查询,忘记了DBI-> quote方法,但它可以使代码更简单,并且在大多数情况下它并不比“适当的”占位符方法慢。
1)使用DBI->引号而不是占位符来构建查询。例如,对于简单的选择:
my $sql = "select foo from bar where baz in ("
. join(",", map { DBI->quote($_) } @bazs)
. ")";
my $data = $dbh->selectall_arrayref($sql);
2)正如jrockway建议的那样 - 使用ORM为你做这种低级别的东西。例如,DBIx :: Class或Rose :: DB :: Object。
答案 3 :(得分:0)
NUM_OF_PARAMS
属性可能有所帮助:
"NUM_OF_PARAMS" (integer, read-only)
The number of parameters (placeholders) in the prepared
statement.
例如,我有一个脚本可以从使用此代码的命令行运行任意SQL:
my $s = $h->prepare($_);
for my $i (1..$s->{NUM_OF_PARAMS}){
my $param = shift @ARGV;
$s->bind_param($i, $param);
print LOG "Bind param $i using $param.\n"
or die "can't append to $opt{log}: $!";
}
$s->execute();
我不能说我已经使用了其他建议的模块,所以他们可以做得更好。