查询返回意外结果

时间:2012-07-15 15:19:36

标签: php sql postgresql operator-precedence

我觉得这个搜索查询没有像我想象的那样工作。我想确定所选的唯一项目是那些ksisoldby相同(虽然不区分大小写,因此ILIKE)到$user的项目。使用ANDOR指定的其他字段可以缩小此选择的范围。

"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";

我是否已正确完成此操作,并且我的数据未正确设置,或者这些AND和/或OR语句是否覆盖WHERE子句?谢谢你的帮助。

1 个答案:

答案 0 :(得分:3)

此处的关键字为operator precedenceANDOR之前绑定。

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)."%'
    )

WHERE子句中的所有项都被计算为一个布尔结果。如果你

  

希望确定所选择的唯一项目是与ksisoldby相同[$]到$ user

的那些项目

然后你必须将OR'ed标准包含在括号中,否则他们将提供替代方式来进行限定。

另一方面,您可以删除AND'对的括号,就像我演示的那样。

我添加了(语法上不相关的)空格和换行符以使其更清晰。


顺便说一句 - 正如评论中提到的那样 - 如果你不想要表中的所有列,列出你想要的那些(就像你拥有它)是最佳方式。


我还会考虑使用prepared statements(或带参数的服务器端函数),而不是构建一个大的查询字符串来阻止SQL注入。您的框架可能提供了一些方法来执行此操作。或者你可以手动完成。

在您不断构建查询字符串时,请使用quote_literal()来清理用户输入。