如何处理参数化查询中的空用户输入?
Posted
技术标签:
【中文标题】如何处理参数化查询中的空用户输入?【英文标题】:How to deal with empty user inputs in a parametrized query? 【发布时间】:2018-01-08 18:39:11 【问题描述】:假设我的 Web 应用程序中有以下查询模板:
`WHERE UPPER(NAME) LIKE UPPER('%$NAME%') AND UPPER(LASTNAME) LIKE UPPER('%$LASTNAME%')`
现在,如果用户在应用程序中为其中一个字段输入空值,会不会影响查询结果?
这可以通过应用程序通过分解查询并在执行期间使用 ifs 构造它来解决,但是对于某些查询,这会使应用程序代码过于复杂。
有没有办法在模板中固有地解决这个问题?仅使用 SQL 语言而不使用应用程序逻辑。
如果我不解决它,如果我只是使用空输入进行查询,那会不会对我的性能影响太大? oracle 是否具有不查询空输入的智能?
基本上:查询NAME LIKE '%%'
之类的内容有多糟糕? Oracle 会忽略这部分查询还是会影响性能(我希望它被忽略,因为这是用户未在表单中输入任何内容的结果)?这是一个简单的示例,但还有更复杂的嵌套查询。
这是一种处理用户未在申请表中输入任何值的懒惰方式,假设他在表单中将name
字段留空,在这种情况下,我希望查询中的所有name
s 都没有构建一个新模板。
将 javascript 标记为应用程序语言。
【问题讨论】:
在某种程度上,你不能试试看会发生什么吗?如果他们这样做,您希望发生什么?您实际上没有过滤;如果$NAME
为空,您将查找所有非空值,因为您将与'%%'
进行比较。那是你要的吗? UPPER(NAME)
可能会影响性能,除非您有基于函数的索引。
@AlexPoole 如果 $NAME 为空我希望它基本上被忽略,因为用户没有在表单中输入任何内容,我必须使用 UPPER 因为这些是区分大小写的字段。但我想知道 Oracle 是否真的忽略了它,或者我必须分解查询并且不包括要忽略的查询以获得更好的性能。
在尝试查询之前验证关键参数。如果缺少某些内容,请告知用户
最好的方法是始终确保您的查询是您想要的,以便返回的数据是可预测的。因此,如果有任何参数可能会影响结果集,甚至可能是不正确的。必须更改您的查询,以便您获得所需的内容。这意味着只运行带有参数的查询,这些参数是获取特定数据集作为结果所需的参数
理想情况下,无论如何您都不会在浏览器中生成原始 SQL,因为这会带来 SQL 注入攻击的风险,更不用说当 name
为 O'Brian
时的失败以及对数据库游标缓存的影响。
【参考方案1】:
1) 永远不要用用户输入直接生成 SQL,否则你会被黑客入侵。搜索“SQL 注入”——仍然是各地黑客的首选方法。
2) 一旦你有了绑定变量以避免被黑客入侵,你的 SQL 语句可以是:
where ( :first_name is null or name like :first_name )
and ( :last_name is null or name like :last_name )
and ...
如果您选择这样做,绑定变量包含前导和尾随 % 符号。优化器自然会过滤掉那些为空的参数。
【讨论】:
问题是我使用的应用程序框架只允许我传递查询的“where”部分,所以我只能控制一个字符串,不能在 oracle 中创建绑定变量。因此,在您的情况下,如果用户没有输入,它将转换为where ('' is null or name like '')
。我愿意为我的问题提供悬赏。
从这个意义上说,Nulls 不适用于平等,所以它是:@name is null or name like @name
问题是用户永远不会插入null,只有一个空字符串,因为它是用javascript构造的【参考方案2】:
在 MS SQL 中,我使用这种方法:
DECLARE @NAME NVARCHAR(100) = NULL
DECLARE @LASTNAME NVARCHAR(100) = '%XYZ%'
select *
from CUSTOMER
WHERE UPPER(LASTNAME) LIKE case when UPPER(@NAME) is null then UPPER(LASTNAME) else UPPER(@NAME) end
AND UPPER(FIRSTNAME) LIKE case when UPPER(@LASTNAME) is null then UPPER(FIRSTNAME) else UPPER(@LASTNAME) end
它给了我这个结果
LASTNAME FIRSTNAME
xyz xyz
【讨论】:
OP 清楚地将其标记为 Oracle,因此提供 MS SQL 解决方案对任何人都没有帮助。另外,您的建议是正确的,但是太复杂了。为什么不where (name is null or .....) and (lastname is null or ....)
? case
在许多情况下都是正确的答案,但在这里它是矫枉过正的。以上是关于如何处理参数化查询中的空用户输入?的主要内容,如果未能解决你的问题,请参考以下文章
您如何处理 Apache Pig 中的空输入文件或丢失的输入文件?