2016-06-13 17 views
5

sto ottenendo l'errore 'Violazione cardinalità', per il seguente SQL:violazione cardinalità DBAL errore

Doctrine \ DBAL \ Exception \ DriverException: si è verificata un'eccezione durante l'esecuzione

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 

con params ["% big%", "% light%"]: SQLSTATE [21000]: Violazione della cardinalità: 1241 Operand dovrebbe contenere 1 colonna/e.

L'errore si verifica solo se nell'elenco dei parametri è presente più di un valore per WHERE (p.name LIKE (?, ?)).

Sto usando executeQuery() e passando l'array come Connection::PARAM_STR_ARRAY. Nella dichiarazione originale sto definizione del punto di problemi come:

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

Sembra che non gli piace ottenere una matrice passata come partial_names. Qualche idea su cosa sta causando questo e su come evitarlo?

+0

Vedi anche http: // stacko verflow.com/questions/1127088/mysql-like-in – bishop

+0

Cosa ti ha fatto pensare che mysql LIKE possa accettare più di un argomento? –

+0

@YourCommonSense Poiché 'foo LIKE ('bar')' è valido in MySQL, penso sia naturale pensare che 'foo LIKE ('bar', 'baz')' sia valido. – bishop

risposta

8

MySQL LIKE è una "funzione di confronto delle stringhe" e come tale confronta una stringa con un'altra, utilizzando "semplice corrispondenza del modello".

Se si controlla lo SQL standard, si noterà che lo BNF grammar for LIKE accetta solo argomenti tipo "carattere" e "ottetto", che sono essenzialmente ciò che chiameremmo stringhe. (C'è qualche dettaglio intorno al fatto che LIKE esegue un binario, carattere per carattere partita sul RHS, che è diverso da come = opera:. foo LIKE 'bar' e foo='bar' possono produrre risultati diversi)

Tutto questo si vuol dire impossibile do LIKE ('a', 'b') perché l'espressione colonnare ('a', 'b') non è come una stringa. O in un linguaggio standard geek, la cardinalità (2) differisce dalla cardinalità prevista (1). Tuttavia, si può fare questo in MySQL e SQLite (forse altri motori):

WHERE foo LIKE ('%bar') 

perché la cardinalità del RHS è 1 (c'è una colonna), che è quello che si aspetta LIKE.

Si desidera qualcosa di efficacemente simile a foo LIKE IN ('a', 'b'), ma questo non esiste neanche (per il motivo standard SQL sopra menzionato). This Q&A mostra alcune soluzioni alternative per tale comportamento, essendo la risposta accettata basata su REGEXP.

Quindi, per aggirare questo errore, è necessario riscrivere la query per utilizzare più LIKE o REGEXP o forse anche qualcosa come FIND_IN_SET.

2

Change

(p.name LIKE (?, ?)) 

a

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

e

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

a

"%big%", "%light%" 
Problemi correlati