预处理语句PHP

时间:2017-03-13 07:14:07

标签: php mysql prepared-statement

我在编写SQL语句时遇到问题:

$statement = $conexion->prepare(
    'SELECT * FROM celulares 
    WHERE (MARCA = :marca )

    AND 

    (CATEGORIA = :categoria1 OR CATEGORIA = :categoria2 OR CATEGORIA = :categoria3) 

    AND 

    (CATEGORIA2 = :categoria1 OR CATEGORIA2 = :categoria2 OR CATEGORIA2= :categoria3) 

    AND 

    (CATEGORIA3 = :categoria1 OR CATEGORIA3 = :categoria2 OR CATEGORIA3 = :categoria3)');

赋予占位符值:

$statement->execute(array(':categoria1' => $categoria1,
                      ':categoria2' => $categoria2,
                      ':categoria3' => $categoria3,
                      ':marca' => $query
                 ));

$查询值可能会因我的应用程序开始而变化,具体取决于某些结果:

if ($entrada == "LG") {
            if ($query == "") {
                    $query = "LG";
            } else {
                    $query = $query . ' OR MARCA = "LG" ';
            }
    }
if ($entrada == "APPLE") {
            if ($query == "") {
                    $query = "APPLE";
            } else {
                    $query = $query . ' OR MARCA = "APPLE" ';
            }
    }

    if ($entrada == "HUAWEI") {
            if ($query == "") {
                    $query = "HUAWEI";
            } else {
                    $query = $query . ' OR MARCA = "HUAWEI" ';
            }
    }

我尝试了很多东西,但没有一个能够得到它返回一个空数组,唯一有效的是改变我预备语句的这一行:

WHERE (MARCA = :marca OR MARCA = :marca2 OR MARCA = :marca3 )

和许多" MARCA"作为结果,我认为这不是最好的方法

更新:

现在在我的查询中尝试使用IN语句(谢谢大家帮助我)

现在看起来像:

$marcas  = array("LG", "HUAWEI"); (Static values for test)
$inQuery = implode(',', array_fill(0, count($marcas), '?'));

$statement = $conexion->prepare(
'SELECT * FROM celulares 
WHERE (MARCA = IN (' . $inQuery . '))

AND 

(CATEGORIA = :categoria1 OR CATEGORIA = :categoria2 OR CATEGORIA =  :categoria3) 

AND 

 (CATEGORIA2 = :categoria1 OR CATEGORIA2 = :categoria2 OR CATEGORIA2= :categoria3) 

AND 

(CATEGORIA3 = :categoria1 OR CATEGORIA3 = :categoria2 OR CATEGORIA3 =       :categoria3)');


foreach ($marcas as $k => $marca) {
$statement->bindValue(($k+1), $marca);

}

$statement->bindValue(':categoria1', $categoria1);
$statement->bindValue(':categoria2', $categoria2);  
$statement->bindValue(':categoria3', $categoria3);

$statement->execute();

获取:警告:PDOStatement :: execute():SQLSTATE [HY093]:参数号无效:命名和位置参数混合

尝试修复它

2 个答案:

答案 0 :(得分:0)

您可以简化查询:

SELECT * FROM celulares 
WHERE (MARCA = :marca )
AND (:categoria1,:categoria2,:categoria3)
  IN (
    (CATEGORIA,CATEGORIA2,CATEGORIA3),
    (CATEGORIA,CATEGORIA3,CATEGORIA2),
    (CATEGORIA2,CATEGORIA,CATEGORIA3),
    (CATEGORIA2,CATEGORIA3,CATEGORIA),
    (CATEGORIA3,CATEGORIA,CATEGORIA2),
    (CATEGORIA3,CATEGORIA2,CATEGORIA)
  )

这样您只需传递一次类别,并将其与三种类别的六种可能排列进行比较。

话虽如此,这表明您的数据库状况非常糟糕。一般来说,有任何类型的“column2”,“column3”系统是一个标志,你需要重组你的数据库 - 你最终得到的查询类型,如上所述,只会变得更糟。

具体来说,在这种情况下,只需添加CATEGORIEA4就会增加您需要定义的排列数量,从6到24 !!

编辑:我完全错过了关于:marcaIN的部分 - 我过于专注于数据库关于类别的糟糕状态,抱歉!

答案 1 :(得分:0)

好吧,我解决了,可能这不是解决问题的最好办法,但我现在有了这个:

我使用POST中的条目填充数组

$query = array();
$index = 0;

foreach ($_POST as $entrada) {
switch($entrada) {
case "SAMSUNG":
$query[] = "SAMSUNG";
break;

case "LG":
$query[] = "LG";
break;

case "APPLE":
$query[] = "APPLE";
break;

case "HUAWEI":
$query[] = "HUAWEI";
break;
}


}
$inQuery = str_repeat('?,', count($query) - 1) . '?';

这是我的新查询:问题是我正在混合“?”使用占位符(:)不推荐

     $statement = $conexion->prepare(
    "SELECT * FROM celulares 
     WHERE ( MARCA IN($inQuery)) 

    AND 

    (CATEGORIA = ? OR CATEGORIA = ? OR CATEGORIA = ?) 

    AND 

    (CATEGORIA2 = ? OR CATEGORIA2 = ? OR CATEGORIA2= ?) 

    AND 

    (CATEGORIA3 = ? OR CATEGORIA3 = ? OR CATEGORIA3 = ?)");

然后我就像那样绑定

$c = 0; 
foreach ($query as $q => $queries) {
        $c++;
        $statement->bindValue(($q+1), $queries);

}


$statement->bindValue($c+1, $categoria1);
$statement->bindValue($c+2, $categoria2);
$statement->bindValue($c+3, $categoria3);
$statement->bindValue($c+4, $categoria1);
$statement->bindValue($c+5, $categoria2);
$statement->bindValue($c+6, $categoria3);
$statement->bindValue($c+7, $categoria1);
$statement->bindValue($c+8, $categoria2);
$statement->bindValue($c+9, $categoria3);

$statement->execute();

$resultados = $statement->fetchAll();

我做了很多测试,有很多查询,它工作正常,可能是一个“脏”的解决方案,但我会继续学习

谢谢大家的帮助!