【问题标题】:Can't figure out placeholders in perl DBI无法找出 perl DBI 中的占位符
【发布时间】:2016-01-27 08:01:54
【问题描述】:

我的代码中出现了一个奇怪的错误,这似乎只在我尝试使用占位符和引号标识符进行查询时发生。我编写了以下子例程来检查条目是否存在,如果存在则返回密钥,如果不存在则返回 null

sub check_exists {
    my $table=$_[0];    #table
    my $col=$_[1];
    my $check=$_[2];   #query for item  
    #check if value exists
    my $sql=sprintf(qq(SELECT COUNT(1) FROM %s WHERE ?=?),
                    $dbh->quote_identifier($table));
    my $sth = $dbh->prepare($sql);
    $sth->execute($col,$check);     
    my $result=$sth->fetch()->[0];
    $sth->finish();        
    #if value exists find the row and return the primary key
    if ($result){   
        my $sql = sprintf(qq(SELECT %s FROM %s WHERE ?=?),
                    $dbh->quote_identifier=$col,
                    $dbh->quote_identifier=$table);
        my $sth2=$dbh->prepare($sql);
        $sth2->execute($col,$check);          
        return ($sth2->fetch()->[0]); #return key
    }
    else {
        return 0;   #else value does not exist and return null
    }    
}

我什至尝试过:

my $result=$dbh->selectrow_array(sprintf(qq(SELECT COUNT(1) FROM %s WHERE ?=?),$dbh->quote_identifier($table)),undef, $col, $check);

不幸的是,它总是返回零。如果我不使用占位符,它似乎可以工作。

my $test=$dbh->selectrow_array(qq(SELECT COUNT(1) FROM ORF1 WHERE idORF1=?),undef,$orf1_crc32)

谁能解释我做错了什么?

【问题讨论】:

  • 如上所述,您不能对列名或表名使用占位符。值只能使用占位符。
  • 我认为您可以将 quote_identifier 用于表和列。
  • 我知道我做错了什么,令人尴尬的是,我没有意识到 WHERE 正在寻找一个列,我认为它是一个值。一旦我也在专栏上使用了quote_identifier(),它现在就可以工作了。谢谢大家!

标签: mysql perl dbi


【解决方案1】:

我认为您将从简化代码并使其按照子例程名称​​所说所做的工作(即检查记录的存在)中受益。您的第二个查询进行了不必要的查找以获取您已知的值,因为您首先将它传递给子例程

为什么不直接做一个简单的count(*),它在当今所有流行的数据库中都得到了优化?零/虚假返回值意味着记录不存在,非零/真实返回值意味着它存在。很简单。

sub check_exists {
    my ($table, $col, $val) = @_;

    my $sql = sprintf(
        q{select count(*) from %s where %s = ?},
        $dbh->quote_identifier($table),
        $dbh->quote_identifier($col)
    );

    return $dbh->selectrow_array($sql, undef, $val);
}

if (check_exists('foo', 'bar', 42)) {
    # do something ...
}

【讨论】:

  • 你说得对,我只是在使用count(1),因为我在一个与查找条目实例相关的线程上看到了该代码。关于分解这两个函数,我需要查看一个条目是否存在以及它是否在哪一行。我想我可以检查该行,如果它抛出错误,那么我知道它不存在?
  • 我的观点不是关于count(*) 与其他东西,而是你的逻辑很奇怪。您的查询归结为select foo from bar where foo=1---如果记录存在,那么您的返回值很有可能(如 100%)正是您传入的值。您是否试图根据一些获取行的主键其他列?
  • 哦,谢谢。我看到我做了什么,但是如果条目确实存在,我会尝试返回主键。我想在第二个查询中我没有选择主键。这只有在我只搜索主键列时才有效。现在我认为最好将它分成两个功能。抱歉,我一定是太累了。
【解决方案2】:

不要在表名或列名中使用占位符或变量。

改为使用 if 语句在完整的 SQL 查询之间进行选择。

例如:

if($option eq 'name'){
    $sql = 'SELECT name FROM users WHERE id = ?';
} elsif {$option eq 'id'){
    $sql = 'SELECT age from users WHERE name = ?';
} else {
    // STUFF
}

这将生成更多代码行,但您的代码将更具可读性。

【讨论】:

    【解决方案3】:

    如果您正确复制了代码。

    my $sql = sprintf(qq(SELECT %s FROM %s WHERE ?=?),
                        $dbh->quote_identifier=$col,
                        $dbh->quote_identifier=$table);
    

    看起来很有趣。我敢打赌你是想说

    my $sql = sprintf(qq(SELECT %s FROM %s WHERE ?=?),
                        $dbh->quote_identifier($col),
                        $dbh->quote_identifier($table));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-07
      • 1970-01-01
      • 2010-12-24
      • 2017-05-20
      • 2012-12-22
      • 2015-06-22
      • 1970-01-01
      • 2020-11-19
      相关资源
      最近更新 更多