【问题标题】:Variable in Quotes in Postgres QueryPostgres查询中引号中的变量
【发布时间】:2017-01-03 23:09:35
【问题描述】:

这可能是一个愚蠢的问题,但我在谷歌上搜索了大部分时间的答案,却一无所获。我正在尝试使以下代码工作,但找不到有关如何在 PHP 中正确格式化准备好的 Postgres 请求的任何帮助。

$foo = $_GET[bar];    

echo $foo; // 5555

//what I'm trying to do:
pg_prepare($dbconn,"table_query","SELECT Members FROM programs WHERE programID = '$1' ");
pg_execute($dbconn,"table_query", array($foo));

如果我用一个值对语句进行硬编码,它可以正常工作,但前提是我包含单引号。我已经尝试了几乎所有可以找到的方法来转义单引号或将引号附加到字符串,但我能得到的只是解析错误。

我错过了什么明显的东西?

编辑:更改了 sn-p 以澄清我得到的变量不包含引号。我尝试添加引号的任何方法都失败了。

【问题讨论】:

    标签: php postgresql quotes


    【解决方案1】:

    让我们研究一个完整的例子。假设您从设置名称 pid 的 GET 查询中获得值。从您的示例查询中,我希望该值是整数的十进制表示,不同于零。它是一个字符串,因为 GET 查询不能提供任何其他内容。

     $pid = $_GET['pid'];
    
     // This is _very_ important.
     // Anything that comes from outside must be validated or sanitized.
     // FILTER_VALIDATE_INT refuses "0" too (correct if needed).
     if (filter_var($pid, FILTER_VALIDATE_INT) === false) {
       // Deal with invalid input 
     }
    
     $result = pg_query_params($dbconn,
         'SELECT Members FROM programs WHERE programID = $1',
         array($pid)
     );
    

    pg_query_params$1$pid 绑定并正确引用它,而您不能在语句周围使用双引号,因为 PHP 会错误地扩展 $1。无需手动在$pid 周围加上引号,因为pg_query_params 会处理这个问题。此外,PostgreSQL 接受带引号和不带引号的整数值,因此在这种情况下摸索引号是没有意义的。

    您可以使用 PHP 数据库对象抽象层 PDO,而不是使用传统的 pg_ 函数。 在这种情况下(忽略您的情况所需的可能选项):

      $dsn = 'pgsql:host='. $host .';port=5432;dbname='. $database;
      $dbh = new PDO($dsn, $user, $password);
      $dbh->prepare('SELECT Members FROM programs WHERE programID = ?');
      $result = $dbh->execute(array($pid)); // $pid as before
    

    【讨论】:

    • 关于你为什么在 SQL 字符串中使用 $1 而不是错误的 '$1' 的一些额外解释可能会有所帮助,并且可能有助于避开不了解 pg_query_params 的人作品。只是一个小建议。
    • 在您的示例中, foo 的值已经有引号。我的函数使用 GET 并绘制一个不带引号的 $foo 值。因此,我认为我需要重新提出关于如何在值周围正确添加引号的问题。我尝试将其转换为字符串并附加单引号似乎不起作用。
    • @AdamAndrews 我已经大大扩展了我的答案。我希望现在一切都清楚了。
    【解决方案2】:

    您应该使用准备好的语句。这应该可以解决您的引用问题,并消除 SQL 注入的主要风险。试试这样的:

    $stmt = $conn->prepare("SELECT Members FROM programs WHERE programID = ?");
    $stmt->bind_param("s", $foo);
    
    $foo = "5555";
    $stmt->execute();
    

    【讨论】:

    • 如果我错了,请纠正我,但我认为我已经在使用准备好的语句。我应该改变方法吗?
    • @AdamAndrews:AFAIK 您使用的是准备好的语句,因为pg_query_params 似乎是 PostgreSQL C API 的一个非常薄的包装器,这也意味着您可以避免注入问题。不是 PHP 人,但我猜 PHP 会尝试在双引号字符串中插入 $1 占位符(因此是 Dario 的单引号),'$1' 是 SQL 中的字符串文字,而 $1 是编号占位符(因此在达里奥的中未引用$1)。
    猜你喜欢
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 2018-02-17
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    相关资源
    最近更新 更多