2

这里是一位新生的 Perl 开发人员。我一直在绞尽脑汁,在网上到处搜索,试图弄清楚这一点……很生气,我来找你寻求澄清。

我有以下代码(只剩下相关部分),其余部分正在工作):

my @arrMissingTids;
@arrMissingTids = %hshTids;

my $missingtid;
foreach $missingtid (@arrMissingTids) {
    print "$missingtid\n";
}

这很好用,返回我想要在数组中的值:

500000246,500000235,500000185,500000237,500000227,500000252

但是,当我将它传递给子例程并将其包含在变量名中时,它不会提供上面写的列表,而只是提供数字 1。代码如下:

myqry(@arrMissingTids);

sub myqry($) {

    my $missingtids = @_;

    $sql = "select 
        i.tid i_tid, i.name i_name
        from 
        instrument i
        where i.tid in ($missingtids)";

    print "$sql/n";
}

打印 $sql 返回以下内容:

Select i.tid i_tid, i.name i_name from instrument i where i.tid in (1)

当我希望它返回以下内容时:

Select i.tid i_tid, i.name i_name from instrument i where i.tid in (500000246,500000235,500000185,500000237,500000227,500000252)

在此先感谢您提供正确方向的任何指示!

4

6 回答 6

7

这里存在三个问题。第一个是使用函数原型,别管它,看看为什么 Perl 5 的函数原型不好?.

第二个是函数调用和函数本身接收方的类型不匹配。要么两次都使用数组,要么两次都使用数组引用。

第三个是将数据作为 SQL 查询的一部分,可能为SQL 注入攻击打开了大门。这可以通过将查询字符串与占位符组合起来与DBI一起使用来安全地缓解。

myqry(@arrMissingTids);
sub myqry {
    my @missingtids = @_;
    $sql = "select
        i.tid i_tid, i.name i_name
        from
        instrument i
        where i.tid in (" . join(',', ('?') x @missingtids) . ")";
    print "$sql\n";
    # $dbh->selectall_arrayref($sql, {}, @missingtids)
}

myqry(\@arrMissingTids);
sub myqry {
    my @missingtids = @{ shift() };
    $sql = "select
        i.tid i_tid, i.name i_name
        from
        instrument i
        where i.tid in (" . join(',', ('?') x @missingtids) . ")";
    print "$sql\n";
    # $dbh->selectall_arrayref($sql, {}, @missingtids)
}
于 2012-05-09T16:22:20.173 回答
5

如果有人还没有提到它,这里的原型是一个问题:

sub myqry($) {

考虑一下:

sub test1($) {
    print "$_\n" foreach @_;
}

sub test2 {
    print "$_\n" foreach @_;
}

my @args = ('a', 'b', 'c');

test1(@args);
test2(@args);      

和输出:

3
a
b
c

到目前为止,您已经意识到标量上下文中的数组只是元素的数量,例如:

my $n = @args;

$n是 3。通过将数组传递给子例程,将其简化为标量,最终得到一个 arg,即数组中元素的数量。然后你这样做:

my $missingtids = @_;

由于子定义中的 ,它总是只有一个($)(数组已经减少到一个元素)。因此,您得到1

0.02 美元:perl 中的 IMO 原型是个坏主意;)

于 2012-05-09T16:30:59.820 回答
1

问题就在这里:

my $missingtids = @_;

@_标量上下文中调用数组。这意味着您正在$missingtids分配@_. 解决此问题的一种方法是传递数组引用:

sub myqry {

    my $missingtids_ref = shift;
    my @missingtids=@$missingtids_ref;

    $sql = "select 
        i.tid i_tid, i.name i_name
        from 
        instrument i
        where i.tid in (" . join(",",@missingtids) . ")";

    print "$sql/n";
}

有关更多信息,请查看perldoc perlrefperldoc perldata

于 2012-05-09T16:23:11.863 回答
0

所以你想创建字符串

... in (1,2,3,4)

采用join

myqry(join(',', @arrMissingTids))

但那是由内而外的。这会更好:

sub myqry {
    my $missingtids = join(',', @_);

    return "select 
        i.tid i_tid, i.name i_name
        from 
        instrument i
        where i.tid in ($missingtids)
    ";
}

myqry(@arrMissingTids);
于 2012-05-09T16:19:45.843 回答
0

感谢所有的帮助。毕竟,我最终摆脱了原型并使用了这段代码,它运行良好,并且是从上面的所有帮助中拼凑而成的:

myqry(@arrTids);

sub myqry {
   $missingtids = join(",",@_);

   .rest of code...
}
于 2012-05-11T16:00:05.527 回答
-1

未经测试,但可能是正确的:

myqry(\@arrMissingTids);

sub myqry($) {

    my $missingtids = shift; # or $_[0]

    $sql = "select 
        i.tid i_tid, i.name i_name
        from 
        instrument i
        where i.tid in (" . join(',', @{$missingtids}) . ")";

    print "$sql/n";
}

当然,您可以传递数组本身而不是引用,但是您需要更改原型并重写数组引用。但上面的东西应该让你继续前进。

于 2012-05-09T16:18:41.757 回答