2016-06-13 4 views
5
나는 다음과 같은 SQL를 들어, '리티 위반'오류를 얻고있다

:DBAL 카디 위반 오류

교리 \ DBAL \ 예외 \의 DriverException :와

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 

을 실행하는 동안 예외가 발생했습니다 params [ "% big %", "% light %"] : SQLSTATE [21000] : 카디널리티 위반 : 1241 피연산자에 1 개의 열이 있어야합니다.

오류는 매개 변수 목록에 WHERE (p.name LIKE (?, ?))에 대해 둘 이상의 값이 정의 된 경우에만 발생합니다.

나는 executeQuery()을 사용하고 있고 배열을 Connection::PARAM_STR_ARRAY으로 전달하고 있습니다. 원래의 진술에서 문제 지점을 다음과 같이 정의하고 있습니다 :

$builder->andWhere('p.name LIKE (:partial_names)'); 

partial_names로 전달 된 배열을 얻는 것이 싫은 것처럼 보입니다. 이 문제의 원인에 대한 아이디어와이를 피하는 방법은 무엇입니까?

+0

도 참조에 http : // stacko verflow.com/questions/1127088/mysql-like-in – bishop

+0

당신은 mysql LIKE가 하나 이상의 인수를 받아 들일 수 있다고 생각하게 만들었습니까? –

+0

@YourCommonSense'foo LIKE ('bar')'는 MySQL에서 유효하기 때문에'foo LIKE ('bar', 'baz')도 유효 할 것이라고 생각하는 것이 자연스러운 것 같습니다. – bishop

답변

8

MySQL LIKE은 "문자열 비교 함수"이므로 "간단한 패턴 일치"를 사용하여 한 문자열을 다른 문자열과 비교합니다.

을 확인하면 BNF grammar for LIKE은 본질적으로 문자열이라고 부르는 "문자 모양"및 "옥텟과 같은"인수 만 허용한다는 것을 알게 될 것입니다. (LIKE=의 작동 방식과는 다른 인 RHS에 이진, 문자 대 문자로 경기를 수행하는 사실 주위에 몇 가지 세부 사항이있다 :. foo LIKE 'bar'foo='bar' 다른 결과가 나타날 수)는

모든 이것은 당신에게 을 의미한다 0이 될 수 없습니다LIKE ('a', 'b') 기둥식이 ('a', 'b')가 끈 같지 않기 때문에. 또는 괴상한 표준 언어에서는 카디널리티 (2)가 예상 카디널리티 (1)와 다릅니다. 그러나 MySQL과 SQLite는 (아마도 다른 엔진)으로이 작업을 수행 할 수 있습니다 RHS의 카디널리티가 1

WHERE foo LIKE ('%bar') 

때문에 어떤 LIKE 예상하는 것입니다, (한 열이 있습니다).

실제로는 foo LIKE IN ('a', 'b')과 비슷한 것을 원하지만 위의 SQL 표준 이유로 인해 존재하지 않습니다. This Q&A은 해당 동작에 대한 몇 가지 대안을 보여 주며, 허용되는 대답은 REGEXP입니다.

이 오류를 해결하려면 복수 LIKE 또는 REGEXP 또는 심지어 FIND_IN_SET과 같은 값을 사용하도록 쿼리를 다시 작성해야합니다.

2

변경

(p.name LIKE (?, ?)) 

(p.name LIKE ? OR p.name LIKE ?) 

["%big%", "%light%"] 

"%big%", "%light%"