query returns unexpected results

核能气质少年 提交于 2019-12-11 07:55:12

问题


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 ANDs and ORs 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!