【问题标题】:How to make dynamic postgres prepared statements in PHP如何在 PHP 中制作动态 postgres 准备好的语句
【发布时间】:2012-08-17 16:06:01
【问题描述】:

我正在尝试使用 postgres 在 PHP 中编写一些准备好的语句。

这有点难解释,所以我就给你演示一下:

$stmt = "SELECT * FROM customer WHERE zip = '$1'";

if(isset($_POST["CITY"])){ 
   $stmt .= "AND city = '$2'";
}

if(isset($_POST["COUNTRY"])){ 
   $stmt .= "AND country = '$3'";
}

$result = pg_prepare("myconnection", "my query", $stmt);

$result1 = pg_execute("myconnection","my query", array("0000","someCity","someCountry"));

抱歉,如果某些代码有误,但这是一个徒手示例。我需要的是能够根据某些变量 isset/not-null 使准备好的语句动态化。 当语句只需要 1 或者我只需要添加 $1 和 $3 而不是 $2 时,在数组中发布 3 个变量时,它似乎不起作用。希望你能理解。

这个周末要用,希望有人知道!

提前谢谢你!

【问题讨论】:

    标签: php postgresql prepared-statement


    【解决方案1】:

    在准备好的语句中,SQL 是有意静态的。一旦准备好语句,参数的数量就不能改变。

    但您的代码很容易根据语句提交正确数量的参数。您可以为参数计数器添加一个变量,以及一个动态 php 数组以传递给 pg_execute 而不是硬编码的文字。它们将在if (isset(...)) 分支内递增/填充。

    【讨论】:

    • 你能试着用一些代码给我看吗?..如果我不清楚,我很抱歉,但可能是我需要原始语句,然后只有“如果”和“国家”。我希望你明白我的意思:)
    【解决方案2】:

    拥有 3 个不同的语句(每种情况一个)并根据传递的参数数量执行适用的语句并没有错。 示例:

    编辑:我修改了代码以匹配所有情况:

    • 仅指定的 zip 文件
    • 邮编 + 城市
    • 邮编 + 国家
    • 邮编 + 城市 + 国家

    (即使有其他情况,你也会明白的)

    $stmt = "SELECT * FROM customer WHERE zip = '$1'";
    
    if(isset($_POST["CITY"]) && isset($_POST["COUNTRY"])) { 
       $stmt3 = $stmt . " AND city = '$2'" . " AND country = '$3'";
    } elseif(isset($_POST["CITY"])) { 
       $stmt1 = $stmt . " AND city = '$2'";
    } elseif(isset($_POST["COUNTRY"])) {
       $stmt2 = $stmt . " AND country = '$2'";
    }
    
    if(isset($stmt3)) {
       $result = pg_prepare("myconnection", "my query", $stmt3);
       $result1 = pg_execute("myconnection","my query", array("0000","someCity","someCountry"));
    } elseif(isset($stmt2)) {
       $result = pg_prepare("myconnection", "my query", $stmt2);
       $result1 = pg_execute("myconnection","my query", array("0000","someCountry"));
    } elseif(isset($stmt1)) {
       $result = pg_prepare("myconnection", "my query", $stmt1);
       $result1 = pg_execute("myconnection","my query", array("0000","someCity"));
    } else {
       $result = pg_prepare("myconnection", "my query", $stmt);
       $result1 = pg_execute("myconnection","my query", array("0000"));
    }
    

    为简洁起见,我省略了(就像你一样)所有错误检查。

    【讨论】:

    • 我明白你的意思,但不幸的是,有时预先准备好的语句只包含 $stmt1 和 $stmt3 :(
    【解决方案3】:

    虽然 Daniel 和 aymeric 都是正确的 - 测试两次没有意义,也没有使用数字。见下文:

    $some_vars = array();
    $some_vars[":zip"] = $_POST["ZIP"];
    $stmt = "SELECT * FROM customer WHERE zip = :zip";
    
    if(isset($_POST["CITY"])){ 
        $some_vars[":city"] = $_POST["CITY"]);
        $stmt .= " AND city = :city";
    }
    
    if(isset($_POST["COUNTRY"])){ 
        $some_vars[":country"] = $_POST["COUNTRY"]);
        $stmt .= " AND country = :country";
    }
    
    $result = pg_prepare("myconnection", "my query", $stmt);
    $result1 = pg_execute("myconnection","my query", $some_vars);
    

    别忘了消毒等等。

    【讨论】:

      【解决方案4】:

      不要进行字符串连接。检查参数是否设置。如果没有将它们设置为空。使用单个查询字符串:

      $zip = $_POST["zip"];
      $city = $_POST["city"];
      $country = $_POST["country"];
      
      if (!isset($zip)) $zip = '';
      if (!isset($city)) $city = '';
      if (!isset($country)) $country = '';
      
      $stmt = "
          select *
          from customer
          where
              (zip = '$1' or '$1' = '')
              and
              (city = '$2' or '$2' = '')
              and
              (country = '$3' or '$3' = '')
      ";
      
      $result = pg_prepare("myconnection", "my query", $stmt);
      $result1 = pg_execute(
              "myconnection",
              "my query",
              array($zip, $city, $country)
              );
      

      每个条件只有在各自的参数不是空字符串时才会被强制执行。

      同样的逻辑可以使用空值而不是空那些包含应该选择的空字符串的列。

      【讨论】:

        猜你喜欢
        • 2021-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-20
        • 2010-09-17
        • 1970-01-01
        • 2015-06-27
        相关资源
        最近更新 更多