PDO - SQLSTATE [HY093]:UNION查询的参数号无效

时间:2014-01-21 00:52:03

标签: php mysql sql pdo

我花了整整一个晚上研究并试图弄清楚我的搜索查询有什么问题。我使用联合查询和分页进行一些通配符搜索。

$current_page = 0;

$search1 = $search;
$search2 = $search."%";
$search3 = "%".$search."%";

$pdo = DB::connection()->getPdo();

$stmt = $pdo->prepare('
    SELECT id, desc FROM table WHERE desc LIKE :search1 LIMIT :skip, 15
    UNION
    SELECT id, desc FROM table WHERE desc LIKE :search2 LIMIT :skip, 15
    UNION
    SELECT id, desc FROM table WHERE desc LIKE :search3 LIMIT :skip, 15
');

$stmt->bindParam(':search1', $search1);
$stmt->bindParam(':search2', $search2);
$stmt->bindParam(':search3', $search3);
$stmt->bindParam(':skip', $current_page, PDO::PARAM_INT);

$stmt->execute();

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

第一个查询(没有联合)工作正常,或者如果我删除:skip参数,它也能正常工作。

任何想法有什么不对?

3 个答案:

答案 0 :(得分:6)

在PDO中使用命名参数,除非您执行以下操作,否则不能多次使用相同的名称:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

但是如果这样做,:skip的值将作为带引号的字符串内插到查询中,这在LIMIT的上下文中无效。换句话说如下:

LIMIT '0', 15

导致语法错误,因为LIMIT只想要真正的整数作为其参数。

有关更多示例和说明,请参阅我对Parametrized PDO query and LIMIT clause - not working

的回答

因此,您可以选择为:skip的每次出现添加一个单独的参数:

$stmt = $pdo->prepare('
    SELECT id, desc FROM table WHERE desc LIKE :search1 LIMIT :skip1, 15
    UNION
    SELECT id, desc FROM table WHERE desc LIKE :search2 LIMIT :skip2, 15
    UNION
    SELECT id, desc FROM table WHERE desc LIKE :search3 LIMIT :skip3, 15
');

$stmt->bindParam(':search1', $search1);
$stmt->bindParam(':search2', $search2);
$stmt->bindParam(':search3', $search3);
$stmt->bindParam(':skip1', $current_page, PDO::PARAM_INT);
$stmt->bindParam(':skip2', $current_page, PDO::PARAM_INT);
$stmt->bindParam(':skip3', $current_page, PDO::PARAM_INT);

或者自己将值插入到查询中,不用引用整数。

但我同意@Class的评论,你根本不需要做UNION。如果不出意外,'%search%'适用于其他两种模式:'search%''%search'。您不必搜索所有三个。

答案 1 :(得分:0)

将每个SELECT括在括号中。

来自documentation

  

要将ORDER BY或LIMIT应用于单个SELECT,请将该子句放在括起SELECT的括号内:

$stmt = $pdo->prepare('
    (SELECT id, desc FROM table WHERE desc LIKE :search1 LIMIT :skip, 15)
    UNION
    (SELECT id, desc FROM table WHERE desc LIKE :search2 LIMIT :skip, 15)
    UNION
    (SELECT id, desc FROM table WHERE desc LIKE :search3 LIMIT :skip, 15)
');

答案 2 :(得分:0)

就像更新一样,如果有人在这里试图实现类似的搜索,通过相关性返回结果,上面的原始查询将复制一些结果,每个选择的限制将跳过一些结果。

经过一些测试后,以下查询似乎按预期完成了工作:

$current_page = ($_GET['page'] - 1) * 15;

$search1 = $search;
$search2 = $search."%";
$search3 = "%".$search."%";

$pdo = DB::connection()->getPdo();

$stmt = $pdo->prepare('
    SELECT id, desc FROM table WHERE desc LIKE :search1
    UNION
    SELECT id, desc FROM table WHERE desc LIKE :search2 AND desc NOT LIKE :search1a
    UNION
    SELECT id, desc FROM table WHERE desc LIKE :search3 AND desc NOT LIKE :search2a
    LIMIT :skip, 15
');

$stmt->bindParam(':search1', $search1);
$stmt->bindParam(':search1a', $search1);
$stmt->bindParam(':search2', $search2);
$stmt->bindParam(':search2a', $search2);
$stmt->bindParam(':search3', $search3);
$stmt->bindParam(':skip', $current_page, PDO::PARAM_INT);

$stmt->execute();

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);