我花了整整一个晚上研究并试图弄清楚我的搜索查询有什么问题。我使用联合查询和分页进行一些通配符搜索。
$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参数,它也能正常工作。
任何想法有什么不对?
答案 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
括在括号中。
要将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);