【问题标题】:How can I insert strings with quotes into Perl DBI queries?如何在 Perl DBI 查询中插入带引号的字符串?
【发布时间】:2010-09-22 00:49:42
【问题描述】:

使用 DBI 将可以包含单引号和双引号 (",') 的字符串插入 MySql 的首选方法是什么?例如,$val1$val2 可以包含引号:

my $dbh = DBI->connect( ... );
my $sql = "insert into tbl_name(col_one,col_two) values($val1, $val2)";
my $sth = $dbh->prepare($sql);
$sth->execute();

【问题讨论】:

    标签: mysql perl


    【解决方案1】:

    使用绑定查询

    $sth = $dbh->prepare("insert into tbl_name(col_one,col_two) values(?,?)");
    $sth->execute($val1, $val2);
    

    如果你使用绑定变量,一切都会为你转义。

    更新:将我的示例更改为与问题中编辑的示例相对应。

    更新:我不知道亚当为什么删除了他的答案,但如果由于某种原因您不能使用绑定变量(又名“占位符”),您也可以在变量上使用 $dbh->quote($var)。例如:

    $sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
        $dbh->quote(q("Don't"));
    

    【讨论】:

    • 一般称为使用占位符。
    • 占位符还具有防止 SQL 注入攻击的非常有用的属性。使用它们。总是。 切勿将用户提供的数据直接放入查询中。
    • 'executeUpdate' 应该只是 'execute' (无论如何它是插入,而不是更新:-) BTW Adam,quote() 也是一个很好的答案,有时它更可取占位符。但是,是的,永远不要在查询中直接使用用户提供的数据,否则会受到 Bobby Tables 的愤怒。
    • @Adam 你不应该删除你的答案。它有一些常见的信息。
    【解决方案2】:

    使用quote() 方法。它将智能地为您处理报价。来自docs 的示例:

    $sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
                $dbh->quote("Don't");
    

    稍作修改以具有两种类型的引号:

    $sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
                $dbh->quote(q("Don't"));
    

    【讨论】:

    • 我也不记得为什么我删除了这个答案。所以我要取消删除它。 :)
    【解决方案3】:

    关于绑定占位符的一个小警告,我构建了一个相当大的数据库加载脚本,该脚本最初在旧版本的 Perl/DBI 中使用绑定占位符,并发现占位符实现中似乎存在内存泄漏,所以如果你'正在考虑在持久进程/守护进程或大容量上下文中使用它们,您可能希望确保进程大小不会成为问题。切换到使用 quote() 方法构建查询字符串为我消除了这个问题。

    【讨论】:

    • 很有趣,尽管它可能只是因为显式创建语句句柄对象而导致 Perl 中的内存管理问题 - 即内存碎片。 Perl 真的不擅长回收释放的内存...
    【解决方案4】:

    DBI 占位符很棒。当您需要在循环中执行相同的查询时,它们会发光。考虑一下:

      my $dbh = DBI->connect(...);
      my $name_pairs = get_csv_data("data.csv");
      my $sth = $dbh->prepare("INSERT INTO t1 (first_name, last_name) VALUES (?,?)");
      for my $pair (@$name_pairs) {
         unless ($sth->execute(@$pair)) {
             warn($sth->errstr);
         }
      }
    

    在这种情况下,使用准备好的语句句柄,呃,很方便。

    但是,除非出现这种紧密循环的情况,否则我希望看到发送到服务器的实际语句。这是我非常依赖报价和坦率地说 sprintf 的地方。

       # Here, I am confident about the hash keys, less so about the values
       $sql = sprintf("INSERT INTO t1 (%s) VALUES (%s)",
                        join(",", keys(%hash)),
                        join("," map { $dbh->quote($_) } values(%hash))
                      );
       $sth = $dbh->prepare($sql);
       unless ($sth->execute) {
         warn($sth->{Statement});
       }
    

    请注意,您必须在 $dbh 上设置 RaiseError => 0 以便您可以看到失败的 SQL,但这在过去对我有很大帮助。

    干杯。

    【讨论】:

    • 不清楚为什么这个准确、礼貌的答案被否决了,但不管怎样。
    猜你喜欢
    • 1970-01-01
    • 2016-06-17
    • 2015-03-25
    • 2015-02-15
    • 2013-01-17
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    相关资源
    最近更新 更多