如何处理参数化查询中的空用户输入?

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 字段留空,在这种情况下,我希望查询中的所有names 都没有构建一个新模板。

javascript 标记为应用程序语言。

【问题讨论】:

在某种程度上,你不能试试看会发生什么吗?如果他们这样做,您希望发生什么?您实际上没有过滤;如果$NAME 为空,您将查找所有非空值,因为您将与'%%' 进行比较。那是你要的吗? UPPER(NAME) 可能会影响性能,除非您有基于函数的索引。 @AlexPoole 如果 $NAME 为空我希望它基本上被忽略,因为用户没有在表单中输入任何内容,我必须使用 UPPER 因为这些是区分大小写的字段。但我想知道 Oracle 是否真的忽略了它,或者我必须分解查询并且不包括要忽略的查询以获得更好的性能。 在尝试查询之前验证关键参数。如果缺少某些内容,请告知用户 最好的方法是始终确保您的查询是您想要的,以便返回的数据是可预测的。因此,如果有任何参数可能会影响结果集,甚至可能是不正确的。必须更改您的查询,以便您获得所需的内容。这意味着只运行带有参数的查询,这些参数是获取特定数据集作为结果所需的参数 理想情况下,无论如何您都不会在浏览器中生成原始 SQL,因为这会带来 SQL 注入攻击的风险,更不用说当 nameO'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 中的空输入文件或丢失的输入文件?

Pyspark:如何处理 python 用户定义函数中的空值

存储过程中的空参数

如何处理 DRF 中的空索引列表?

如何处理 JSONDecoder 中的空日期字符串

你如何处理重复的街道后缀?