问题
I feel like this search query is not working as I imagined it would. I want to be certain that the only items selected are those with ksisoldby
identical (though case-insensitive, thus ILIKE
) to $user
. And the the other fields specified with the AND
s and OR
s are possible ways this selection could be narrowed down.
"SELECT
id,
status,
customer_id,
shipping_address_id,
order_number,
reference,
ship_via_id,
order_date :: date,
due_date :: date,
created,
sales_tax,
freight,
taxable,
nontaxable,
job_name,
order_description,
ship_to_name,
ship_to_address1,
ship_to_address2,
ship_to_city,
ship_to_state,
ship_to_zipcode,
name,
address1,
address2,
city,
state,
zipcode,
act_ship_date,
ksisoldby
FROM sales_orders
WHERE ksisoldby ILIKE '".$user."'
AND (order_description ilike
'%".implode("%' AND order_description like '%", $search)."%')
OR (order_number ilike
'%".implode("%' AND order_number like '%", $search)."%')
OR (name ilike
'%".implode("%' AND name like '%", $search)."%')
OR (reference ilike
'%".implode("%' AND name like '%", $search)."%')
ORDER BY order_number DESC";
Have I done this correctly, and it is my data that is not set up correctly, or are these AND
and/or OR
statements overriding the WHERE
clause? Thanks for the help.
回答1:
The keyword here is operator precedence. AND
binds before OR
.
WHERE ksisoldby ILIKE '".$user."'
AND (
order_description ilike '%".implode("%'
AND order_description like '%", $search)."%')
OR order_number ilike '%".implode("%'
AND order_number like '%", $search)."%'
OR name ilike '%".implode("%'
AND name like '%", $search)."%'
OR reference ilike '%".implode("%'
AND name like '%", $search)."%'
)
All items in the WHERE
clause are evaluated to one boolean result. If you
want to be certain that the only items selected are those with ksisoldby identical [...] to $user
then you have to wrap the OR
'ed criteria into parenthesis or they will offer alternative ways to qualify.
On the other hand, you can remove the parenthesis around the AND
'ed pairs like I demonstrate.
I added (syntactically irrelevant) white space and line breaks to make it clearer.
BTW - as this came up in the comments - if you don't want all columns from the table, listing the ones you want (like you have it) is the optimal way.
I would also consider to use prepared statements (or server-side functions with parameters) instead of building one big query strings to prevent SQL injection. Your framework probably offers some way to do this. Or you can do it manually.
While you keep building query strings, use quote_literal() to sanitize user input.
来源:https://stackoverflow.com/questions/11493106/query-returns-unexpected-results