【问题标题】:SQLite & Perl Query Issue with Email Address电子邮件地址的 SQLite 和 Perl 查询问题
【发布时间】:2016-09-19 01:54:21
【问题描述】:

我正在尝试查询 SQLite3 数据库(准备构建一个基于 perl 的网页,并为大学作业提供身份验证)。我遇到的问题是数据库在尝试通过电子邮件地址查询时返回空结果,该电子邮件地址也是该数据库的用户名。

查询如下:

my $sql = "SELECT * FROM accounts WHERE email_address = 'xxxxx@xxxxx.xxxxx.edu.au'";
my $sth = $dbh->prepare( $sql ) or die( "Can't prepare: " . $dbh->errstr() );
$sth->execute() or die( "Can't execute: " . $sth->errstr() );

my @row;
while( @row = $sth->fetchrow_array() )
{
    print join( q/, /, @row ), "\n";
}

这会打印出一个空结果。然而,如果我要通过数据库上的 first_name 或 last_name 字段进行查询,我就能够将数据打印出来。

电子邮件地址格式如下:xxx@xxx.xxx.edu.au

数据库结构如下:

accounts(
email_address VARCHAR(50) PRIMARY KEY,
last_name VARCHAR(30) NOT NULL,
first_name VARCHAR(30) NOT NULL,
password VARCHAR(100) NOT NULL,
pass_salt VARCHAR(10) NOT NULL,
account_balance DOUBLE
);

任何人都可以提供任何建议将不胜感激!

【问题讨论】:

    标签: perl sqlite email


    【解决方案1】:

    您正确地确定了问题所在,但您的解决方案不是最优的。与其在代码中手动转义输入,不如使用placeholders。 DBI 让这一切变得非常舒适。

    将不带引号的? 放入SQL 中,然后将参数传递给execute。 DBI 将处理 SQL 中所有带有含义的字符的转义,从而使 SQL 注入成为不可能。在这种情况下,这不是问题,但这是一个不错的奖励。

    my $email = 'xxxxx@xxxxx.xxxxx.edu.au';
    my $sql = "SELECT * FROM accounts WHERE email_address = ?";
    my $sth = $dbh->prepare($sql) or die "Can't prepare: " . $dbh->errstr;
    $sth->execute($email) or die "Can't execute: " . $sth->errstr;
    
    my @row;
    while ( @row = $sth->fetchrow_array ) {
        print join( q/, /, @row ), "\n";
    }
    

    当然,您也可以简单地对整个 SQL 使用单引号 ',因为无论如何您都没有进行任何变量插值。但是,您应该始终使用占位符


    您似乎正在尝试生成 CSV 文件。看看Text::CSV,它会让你的生活更轻松。

    【讨论】:

      【解决方案2】:

      关于 perl 将数组插入字符串是正确的,但您也应该看到一条警告您的消息

      Possible unintended interpolation of @xxxxx in string
      

      在您的 SQL 字符串中使用 占位符 并将调用中的真实数据传递给 execute 会更好。它的优点是您只需prepare 一次您的SQL 语句,但execute 多次使用不同的电子邮件地址值。它还为您处理任何必要的值引用

      我建议你的代码应该是这样的

      my $account_by_email = $dbh->prepare('SELECT * FROM accounts WHERE email_address = ?');
      
      $account_by_email->execute('xxxxx@xxxxx.xxxxx.edu.au');
      
      while ( my @row = $account_by_email->fetchrow_array ) {
          print join( ', ', @row ), "\n";
      }
      

      【讨论】:

        【解决方案3】:

        好吧,我瞎了,大家不理我。忘记 @ 指示 perl 中的数组,我没有考虑转义电子邮件地址中的 @ 符号。所以看起来电子邮件地址需要一点正则表达式来确保查询可以通过。

        简单的解决方案:

        my $sql = "SELECT * FROM accounts WHERE email_address = 'xxxxx\@xxxxx.xxxxx.edu.au'";
                                                                      ^ inserted escape char!
        

        【讨论】:

        • 更好的方法是使用单引号而不是双引号。由于您的字符串已经包含电子邮件地址周围的单引号,因此您需要使用 q// 来提供替代分隔符。 q{SELECT * FROM accounts WHERE email_address = 'xxxxx@xxxxx.xxxxx.edu.au'} 可以正常工作
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-19
        • 1970-01-01
        • 2011-05-06
        • 2012-04-08
        • 2021-04-13
        • 1970-01-01
        相关资源
        最近更新 更多