Ошибка нарушения мощности DBAL
Я получаю ошибку "Нарушение мощности" для следующего SQL:
Доктрина\DBAL\Исключение\Исключение драйвера: Исключение возникло во время выполнения
SELECT p.* FROM mod_products_products p
LEFT JOIN mod_products_products_categories c_link ON c_link.product_id = p.id
LEFT JOIN mod_products_brands b ON p.brand_id = b.id
LEFT JOIN mod_products_groups vg ON p.variation_id = vg.id
LEFT JOIN mod_products_categories c ON c_link.category_id = c.id
LEFT JOIN mod_products_group_options vg_o ON vg_o.group_id = vg.id
LEFT JOIN mod_products_group_values vg_o_v ON vg_o_v.option_id = vg_o.id
WHERE (p.name LIKE (?, ?)) AND (p.parent_id = 0) AND (vg_o.disabled=0)
GROUP BY p.id ORDER BY p.name ASC
LIMIT 18446744073709551615 OFFSET 0
с параметрами ["%большой%", "%легкий%"]: SQLSTATE[21000]: Нарушение мощности: 1241 Операнд должен содержать 1 столбец(ы).
Ошибка возникает только в том случае, если в списке параметров определено более одного значения для WHERE (p.name LIKE (?, ?))
.
Я использую executeQuery()
и передаю массив как Connection::PARAM_STR_ARRAY
. В исходном заявлении я определяю проблемную точку следующим образом:
$builder->andWhere('p.name LIKE (:partial_names)');
Похоже, ему не нравится, когда массив передается как частичные имена. Есть идеи о том, что является причиной этого и как этого избежать?
2 answers
MySQL, ПОДОБНЫЙ , является "функцией сравнения строк" и, как таковой, сравнивает одну строку с другой, используя "простое сопоставление шаблонов".
Если вы проверите стандарт SQL, вы заметите, что грамматика BNF для LIKE
принимает только "символьные" и "октетные" аргументы, оба из которых по сути являются тем, что мы бы назвали строками. (Есть некоторые детали, касающиеся того факта, что LIKE
выполняет двоичное сопоставление символов в RHS, которое отличается от того, как работает =
: foo LIKE 'bar'
и foo='bar'
могут давать разные результаты.)
Все это означает, что вы не можете сделать LIKE ('a', 'b')
, потому что столбчатое выражение ('a', 'b')
не похоже на строку. Или, выражаясь вызывающим стандартным языком, его мощность (2) отличается от ожидаемой мощности (1). Однако вы можете сделать это в MySQL и SQLite (возможно, в других движках):
WHERE foo LIKE ('%bar')
Потому что мощность RHS равна 1 (есть один столбец), что и ожидает LIKE
.
Ты требуется что-то эффективно похожее на foo LIKE IN ('a', 'b')
, но этого тоже не существует (по причине стандарта SQL, упомянутой выше). Этот вопрос и ответ показывает некоторые обходные пути для такого поведения, REGEXP
основанные на принятом ответе.
Итак, чтобы обойти эту ошибку, вам нужно переписать свой запрос, чтобы использовать несколько LIKE
, или REGEXP
, или, может быть, даже что-то вроде FIND_IN_SET
.
Изменение
(p.name LIKE (?, ?))
До
(p.name LIKE ? OR p.name LIKE ?)
И
["%big%", "%light%"]
До
"%big%", "%light%"