如何将Perl数组作为标量传递到子例程中?

时间:2012-05-09 16:13:26

标签: arrays perl scalar

这是一位新生的Perl开发者。我一直在wra my my and and and and ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

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

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";
}

Print $ 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)

提前感谢任何指向正确的方向!

6 个答案:

答案 0 :(得分:7)

这里有三个问题。第一个是使用函数原型,只需将其遗漏,请参阅Why are Perl 5's function prototypes bad?

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

第三是将数据视为SQL查询的一部分,可能会打开SQL injection attack的门。通过将查询字符串与占位符组合在一起以便与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)
}

答案 1 :(得分: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原型是一个坏主意;)

答案 2 :(得分: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

答案 3 :(得分: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);

答案 4 :(得分:0)

感谢所有帮助。毕竟说完了之后,我最终摆脱了原型并使用了这个代码,这个代码完美无缺,并且从上面的所有帮助拼凑而成:

myqry(@arrTids);

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

   .rest of code...
}

答案 5 :(得分:-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";
}

当然你可以传递数组而不是引用,但是你需要更改原型并重写数组引用。但上面的内容应该让你去。