3

我有一个 Web 表单,允许用户根据传递给 proc 的参数搜索和编辑 Oracle 表中的记录。这是我的数据:

CAE_SEC_ID  SEC_CODE  APPR_STATUS
1           ABC1      100
2           ABC2      100
3           ABC3      101
4           (null)    101
5           (null)    102
6           ABC4      103

这是 where 子句:

select foo 
  from bar 
 where CAE_SEC_ID = NVL(p_cae_sec_id,CAE_SEC_ID)
   and Upper(SEC_CODE) like '%' || Upper(NVL(p_sec_code,SEC_CODE)) || '%'
   and APPR_STATUS = NVL(p_appr_status, APPR_STATUS)

如果任何参数有值,对参数使用 nvl 应该只返回匹配的记录,如果没有参数有值,则返回所有记录。一切都很标准,我想。但是,当我在没有任何参数值的情况下进行搜索时,查询不会返回带有空 SEC_CODE 的记录,即只返回记录 1、2、3 和 6。上面的 where 子句不应该包含具有空 SEC_CODE 值的记录吗?

4

4 回答 4

7

问题是SEC_CODE表中的值为NULL。这意味着它UPPER(sec_code)是 NULL 并且您的第二个谓词简化为

and NULL LIKE '%%'

就像 NULL 不等于任何东西,也不等于任何东西,它也不像任何东西。最有可能的是,您想要类似的东西

and (Upper(SEC_CODE) like '%' || Upper(NVL(p_sec_code,SEC_CODE)) || '%' or
     (sec_code is null and p_sec_code is null))

如果为 NULL,则将返回每一行,但如果为非 NULL P_SEC_CODE,则仍应用过滤器。P_SEC_CODE

于 2011-03-02T23:18:57.707 回答
4

不,不应该。

数据库中的 SEC_CODE 为空,因此 UPPER(SEC_CODE) 为空,因此它将在 LIKE 匹配或几乎任何其他超出 IS NULL 的比较时失败。从技术上讲,它是 UNKNOWN 而不是 FALSE,但不足以通过测试。

于 2011-03-02T23:16:10.803 回答
3

该表达式的NULL = NULL计算结果为NULL,但不是true,因此不会返回这些行。如果我正确理解了要求,您只想过滤参数是否与 null 不同,因此我将像这样重写查询以使过滤器更加明确:

select foo from bar 
where (p_cae_sec_id is null or CAE_SEC_ID = p_cae_sec_id)
and (p_sec_code is null or Upper(SEC_CODE) like '%' || Upper(p_sec_code) || '%')
and (p_appr_status is null or APPR_STATUS = p_appr_status)

将 p_sec_code 参数设置为 null 现在将返回所有行,忽略 SEC_CODE 列中的值。

于 2011-03-02T23:33:01.750 回答
0

我们也可以像这样写 Jorn 的查询

select foo from bar 
where (CASE WHEN p_cae_sec_id is null THEN 'Y'
            WHEN CAE_SEC_ID = p_cae_sec_id THEN 'Y'
                    ELSE 'N'
                    END)='Y'
and   (CASE WHEN p_sec_code is null THEN 'Y'
            WHEN Upper(SEC_CODE) like '%' || Upper(p_sec_code) || '%' THEN 'Y'
                    ELSE 'N'
                    END)='Y'
and (CASE WHEN p_appr_status is null THEN 'Y'
                    WHEN APPR_STATUS = p_appr_status THEN 'Y'
                ELSE 'N'
                END)='Y'

使其具体化并提高性能。

于 2011-03-03T19:09:43.950 回答