【问题标题】:perl variable to moduleperl 变量到模块
【发布时间】:2018-03-03 15:35:09
【问题描述】:

我正在尝试执行存储在模块中的查询,但查询中有一些从主文件中读取的变量并且无法正常工作。

模块内无法访问主文件中的变量(其为空白)。

代码如下:

sql.pm

package sql;

use parent 'Exporter'; 

our @EXPORT = qw(%query);

our %query = (
    one => "SELECT isnull(BusinessEntityID, '') as BusinessEntityID,
       isnull(Title, '') as Title,
       isnull(FirstName, '') as FirstName,
       isnull(LastName, '') as LastName,
       isnull(Suffix, '') as Suffix,
       isnull(JobTitle, '') as JobTitle

FROM HumanResources.vEmployee
where BusinessEntityID = ".$id."
order by BusinessEntityID"

);

1;

ma​​in.pl

use strict;
use warnings;

use sql;

my $id = 273;
my $query_main = "$query{one}";

print $query_main;

这将使用 where BusinessEntityID = 而不是 where BusinessEntityID = 273 打印查询

谢谢!

【问题讨论】:

  • 在sql包里面创建一个函数get_query { my ($id)=@_; %query=...}。叫它my $query_main=sql::get_query($id);
  • 请阅读bobby-tables.com 并使用占位符而不是直接将变量插入到查询中。
  • @wolfrevokcats 谢谢你的快速回复,它有帮助,但我还有更多(50+)依赖于各种 foreach/ifs 等。有没有更简单的方法而不必声明每个模块中的变量?我在想是否可以从 main.pl 导出所有变量并将它们导入 sql.pm
  • @rooger 全局变量几乎总是一个坏主意。你会失去对它的控制。在我从事的几份工作中,我不得不与使用全局变量的现有程序进行大量斗争。如果你有很多变量,你应该使用散列并将其传递给函数,至少
  • @tinita 谢谢你的快速回复,如果可以的话,你能给我一个简单的例子吗?

标签: perl perl-module


【解决方案1】:

sql 包的范围内没有词法 $id 变量,因此它被评估为undef,它被字符串化为空字符串

当您尝试运行程序时会看到警告消息。请不要忽视它们,尤其是在您寻求帮助时:它们非常重要

请合理命名您的模块。像sql 这样的名称表示pragma,并影响以下所有代码。一个模块将使用 Capital::Letters 并且应该与 CPAN 中的任何内容都非常不同

我认为你应该将你的库限制为仅包含常量的子例程,并且你应该避免将值插入到 SQL 查询字符串中

例如

package My::Sql;

use Exporter 'import';

our @EXPORT = qw/
    QUERY_ONE
/;

use constant {
    QUERY_ONE => "SELECT isnull(BusinessEntityID, '') as BusinessEntityID,
       isnull(Title, '') as Title,
       isnull(FirstName, '') as FirstName,
       isnull(LastName, '') as LastName,
       isnull(Suffix, '') as Suffix,
       isnull(JobTitle, '') as JobTitle

FROM HumanResources.vEmployee
where BusinessEntityID = ?
order by BusinessEntityID"

);

1;

如果你那么

use My::Sql;

my $sth = $dbh->prepare(QUERY_ONE);
$sth->execute(42);

那么你的代码至少应该可以正常工作,但设计仍然很缺乏

【讨论】:

  • 谢谢,我会这样!
【解决方案2】:

当然,在 Perl 中可以从另一个包访问一个包的全局变量。
但这意味着您必须将所有 localmy 变量转换为全局变量。
这将是一团糟。
我强烈建议不要这样做。

简化占位符变量管理的方法之一是使用Template Toolkit,如下所示:

#!/usr/bin/perl
use strict;
use warnings;
use Template;

my $template = <<'CUT';
SELECT isnull(BusinessEntityID, '') as BusinessEntityID,
       isnull(Title, '') as Title,
       isnull(FirstName, '') as FirstName,
       isnull(LastName, '') as LastName,
       isnull(Suffix, '') as Suffix,
       isnull(JobTitle, '') as JobTitle

FROM HumanResources.vEmployee
where BusinessEntityID = [% id %]
order by BusinessEntityID
CUT
;

my $id=100;
my ($param1,$paramN);
my $vars = {
    'id'=>$id,
    'param1'=>$param1,
     #...
    'paramN'=>$paramN,
};

my $tp = Template->new();
my $out;
$tp->process(\$template, $vars, \$out)
    || die $template->error();
print($out);

输出

SELECT isnull(BusinessEntityID, '') as BusinessEntityID,
       isnull(Title, '') as Title,
       isnull(FirstName, '') as FirstName,
       isnull(LastName, '') as LastName,
       isnull(Suffix, '') as Suffix,
       isnull(JobTitle, '') as JobTitle

FROM HumanResources.vEmployee
where BusinessEntityID = 100
order by BusinessEntityID

但是,如果您要使用不同的参数多次运行相同的查询,则应使用 Borodin 的答案中所示的参数绑定,以避免性能损失。

【讨论】:

  • 感谢您的帮助!我会听从您的建议并使用 Borodin 的答案,因为我必须多次运行查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 2011-02-08
相关资源
最近更新 更多