我有多个查询,可能需要执行多达100行甚至更多行,我正在寻找最佳实践/简单方法将查询从模块导入到我的主文件中,绑定值并执行它们。例:
Sql.pm
package Sql;
use strict;
use warnings;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw($query);
our $query = "SELECT *
FROM ?
";
Main.pl
use strict;
use warnings;
use Sql;
#use DBI & connect ;
my $select = $Sql::query;
my $tbl= 'my_tbl';
my $sth = $dbh->prepare($select );
$sth->execute($tbl);
这会给我这个错误:
ct_result(ct_dynamic(CS_PREPARE))在/usr/lib/x86_64-linux-gnu/perl5/5.22/DBD/Sybase.pm第138行返回-205。
DBD :: Sybase :: db prepare failed:服务器消息号= 1087严重性= 16状态= 1行= 1服务器=本地文本=必须声明表变量“@ P1”。服务器消息号= 8180严重性= 16状态= 1行= 1服务器= localtext =无法准备语句。在main.pl第16行。
无法在main.pl第17行的未定义值上调用方法“execute”。
如果我在main.pl
中这样做my $sth = $dbh->prepare($select);
$sth->bind_param(1, $tbl);
$sth->execute(1);
我得到了同样的错误,但告诉我'无法调用方法'bind_param“对未定义的值'
我做错了什么? 是否有更好/更容易/最佳实践方式来实现我想要做的事情?
由于
答案 0 :(得分:0)
我希望以下内容足够自我解释:
package My_App::Table_Name;
use feature 'state';
# save performance hit on `prepare` statements
# you said SQL statements of 100+ lines
sub sql_name {
my $class = shift;
my $dbh = shift;
my %params = @_;
# do some checking on the params if needed, or use Type::Params::compile
state $sth = $dbh->prepare( << END_OF_SQL ); # 4 spaces for neatness
SELECT * FROM table_name WHERE col_foo = ? AND col_bar = ?
END_OF_SQL
$sth->execute(
$params{foo},
$params{bar},
);
return $sth->fetchall_hashref('id'); # or what ever
}
1;
然后在你的应用中:
use strict;
use warnings;
use DBI;
use My_App::Table_Name;
my $dbh = ... ; # RaiseError is your friend
my $results = My_App::Table_Name->sql_name($dbh,
foo => 'abc',
bar => '123',
);
# $results now contains a HashRef where the keys are the id's from the returned
# rows, each row being a HashRef itself, so you can do things like:
say $results->{42}->{col_foo};
这样,您可以按表名,大多数数据库组织SQL语句 修改在一个表上执行,或者由于一个表内的更改,导致链接在其他地方更新。
在每个模块中,您现在可以创建具有合理名称的子例程,例如
sub create { ... };
sub delete { ... };
sub search_joined_with_table_other { ... };
因此在您的应用中:
My_App::Table_Name->create($dbh,
foo => 'xyz',
bar => '345',
);
My_App::Table_Other->delete($dbh, id => 42 );
所以,基本上,你不关心主应用程序中的所有SQL,但很好地将它们移到自己的包中。在你的应用程序中,你甚至不需要知道底层有SQL,你只需要调用类方法。
下一级,将为每个Table_Name包返回Row Objects,并在其上拥有自己的实例方法。
快乐编码并记住TIMTOWTDI(有多种方法可以做到)