什么是通过pdo多次绑定相同参数的更简洁方法

时间:2014-08-29 13:20:21

标签: php mysql pdo

我有一个MySQL查询字符串,其中包含许多未命名的占位符(?),每个字符都接受相同的参数:

$sql = "SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value, ".
           "CASE ".
               "WHEN A1.pagetitle LIKE ? THEN 1 ".
               "WHEN A1.content LIKE ? THEN 2 ".
               "WHEN A2.value LIKE ? THEN 3 ".
           "END AS rank ".
       "FROM mod_site_content A1 ".
       "LEFT JOIN mod_site_tmplvar_contentvalues A2 ".
           "ON A1.id = A2.contentid ".
           "AND A2.tmplvarid IN(15,17) ".
       "WHERE (pagetitle LIKE ? ".
           "OR content LIKE ? ".
           "OR value LIKE ?) ".
       "ORDER BY rank";

$stmt = $db->prepare($sql);
$searchq = "%".$searchq."%";

目前我正在重复绑定,看起来似乎很冗长:

$stmt->bindParam(1, $searchq, PDO::PARAM_STR);
$stmt->bindParam(2, $searchq, PDO::PARAM_STR);
$stmt->bindParam(3, $searchq, PDO::PARAM_STR);
...etc

将相同参数绑定到任意数量的占位符是否有更整洁,更可维护的方式?

编辑:php版本5.10.1

3 个答案:

答案 0 :(得分:1)

一个简单的循环就可以了。

foreach($i = 1; $i <= 3; ++$i) {
  $stmt->bindParam($i, $searchq, PDO::PARAM_STR);
}

或者,如果您要遗漏一些指数:

foreach($i in range(1,3,4,7)) {
  $stmt->bindParam($i, $searchq, PDO::PARAM_STR);
}

答案 1 :(得分:1)

如何写这样的查询?

SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value, 
       (CASE WHEN A1.pagetitle LIKE vars.pattern THEN 1 
             WHEN A1.content LIKE vars.pattern THEN 2
             WHEN A2.value LIKE vars.pattern THEN 3
             . . .
       ) as val
FROM . . . CROSS JOIN
     (SELECT ? as pattern) vars
. . .

然后你只需要包括一次。

编辑:

您的查询将如下所示:

SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value,
       (CASE WHEN A1.pagetitle LIKE vars.pattern THEN 1
             WHEN A1.content LIKE vars.pattern THEN 2
             WHEN A2.value LIKE vars.pattern THEN 3
        END) AS rank
FROM mod_site_content A1 LEFT JOIN
     mod_site_tmplvar_contentvalues A2
     ON A1.id = A2.contentid AND A2.tmplvarid IN (15, 17) CROSS JOIN
     (SELECT ? as pattern) vars
WHERE (pagetitle LIKE vars.pattern OR content LIKE vars.pattern OR value LIKE vars.pattern);
ORDER BY rank;

您可以使用having

来简化此操作
SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value,
       (CASE WHEN A1.pagetitle LIKE vars.pattern THEN 1
             WHEN A1.content LIKE vars.pattern THEN 2
             WHEN A2.value LIKE vars.pattern THEN 3
        END) AS rank
FROM mod_site_content A1 LEFT JOIN
     mod_site_tmplvar_contentvalues A2
     ON A1.id = A2.contentid AND A2.tmplvarid IN (15, 17) CROSS JOIN
     (SELECT ? as pattern) vars
HAVING rank > 0
ORDER BY rank;

然后,如果&#34;模式&#34;没有使用通配符,你可以这样做:

SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value,
       field(vars.pattern, A1.pagetitle, A1.content, A2.value) AS rank
FROM mod_site_content A1 LEFT JOIN
     mod_site_tmplvar_contentvalues A2
     ON A1.id = A2.contentid AND A2.tmplvarid IN (15, 17) CROSS JOIN
     (SELECT ? as pattern) vars
HAVING rank > 0
ORDER BY rank;

此时,您只有一次模式,所以如果您的模式没有通配符,这应该可以

SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value,
       field(?, A1.pagetitle, A1.content, A2.value) AS rank
FROM mod_site_content A1 LEFT JOIN
     mod_site_tmplvar_contentvalues A2
     ON A1.id = A2.contentid AND A2.tmplvarid IN (15, 17)
HAVING rank > 0
ORDER BY rank;

答案 2 :(得分:0)

由于我没有真正尝试过这个解决方案,因此存在downvotes的风险,我会尝试这些方法:

$sql = "SELECT DISTINCT A1.pagetitle, A1.content, A1.uri, A2.value, ".
           "CASE ".
               "WHEN A1.pagetitle LIKE CONCAT('%', :my_str, '%') THEN 1 ".
               "WHEN A1.content LIKE CONCAT('%', :my_str, '%') THEN 2 ".
               "WHEN A2.value LIKE CONCAT('%', :my_str, '%') THEN 3 ".
               ...etc

$pdo->bindValue(':my_str', $stuff);