Oracle SQL - 如何使用可选搜索参数构建where子句

时间:2015-05-26 09:39:57

标签: oracle optional-parameters

页面中有四个字段可以说

EMPLOYEE ID
DEPT
LOCATION
UNIT:

用户可以输入任何字段值都是可选的,如果他输入EMPLOYEE ID,则查询应返回与该EMPLOYEE ID相关的行。如果他只输入LOCATION,那么查询应该返回该位置的所有员工。如何使用可选参数编​​写where子句条件。

5 个答案:

答案 0 :(得分:4)

如果在谓词中使用NVL,Oracle可能会构建一个优化良好的查询:

select *
  from employee
 where employee_id = nvl(:employee_id, employee_id)
   and dept = nvl(:dept, dept)
   and location = nvl(:location, location)
   and unit = nvl(:unit, unit)

以上代码大致相当于LeoLozes的答案。虽然他的答案更具可读性,但在这种情况下,神秘版本可能运行得更快。一个重要的区别是,如果列为NULL,则上述代码将不起作用。如果您有可以为空的列,则需要使用类似LeoLoze的答案,因为null = null不是真的。

Oracle用于NVL技巧,可以使用FILTER操作自动将此静态查询转换为动态查询。执行计划将同时具有FULL TABLE SCAN和INDEX RANGE SCAN,并将在运行时选择适当的一个,具体取决于绑定变量的值。请参阅我的回答here,了解一些示例代码,了解其工作原理。

答案 1 :(得分:2)

嗯,总是有(非常差的优化)选项这样做:

SELECT * 
FROM EMPLOYEE 
WHERE (EMPLOYEE_ID = :p_EMPLOYEE_ID OR :p_EMPLOYEE_ID IS Null)
  AND (DEPT = :p_DEPT OR :p_DEPT IS Null)
  AND (LOCATION = :p_LOCATION OR :p_LOCATION IS Null)
  AND (UNIT = :p_UNIT OR :p_UNIT IS Null)

我只在少量行的表中使用它。 但是建议至少有一个强制参数使用索引字段(因为在这里,你将有一个 TABLE ACCESS FULL )。

答案 2 :(得分:1)

对于真实世界的应用程序,我建议不要考虑这种想法。向数据库提交动态样式查询已经证明在安全性,优化和功能正确性方面存在问题。 由于用户界面和数据库之间会有一些应用程序代码,因此最好根据需要构建查询,然后提交执行。

答案 3 :(得分:0)

根据他们所选择的内容,只有安全的方式来编写代码的个人视图。例如,如果您使用Java GUI,则可以根据他们想要搜索的内容选择信息。

答案 4 :(得分:0)

select *
  from employee
 where nvl(employee_id, -1) = coalesce(:employee_id, employee_id, -1)
   and nvl(dept, -1) = coalesce(:dept, dept, -1)
   and nvl(location, -1) = coalesce(:location, location, -1)
   and nvl(unit, -1) = coalesce(:unit, unit, -1)

其背后的原因是,按照乔恩(Jon)建议的方式使用nvl有一个缺点:如果要测试的字段本身是null,它将在该测试中返回false,因为(相信)以测试null,则需要使用is null对其进行测试。

nvl可能在此处执行null = null而不是null is null,返回错误的数据,您甚至不会注意到它,因为它不会警告您。

使用coalesce,当参数和字段均为-1 = -1时,您将获得null(或该列认为不可能的其他任何值)