Bug UPPER(变量)

时间:2015-06-11 14:28:02

标签: oracle plsql

我试图检查邮政编码是否有效。示例代码中的邮政编码无效。所以它不应该返回任何值。

postcode := '1059NJ';
SELECT P.POSTCODE INTO test3
FROM POSTCODE P
WHERE P.POSTCODE = UPPER(postcode)
AND P.CITY = INITCAP(LOWER('Amsterdam'))
AND P.STREET = INITCAP(LOWER('Aalsmeerweg'))
AND 14 BETWEEN P.MINNUMBER AND P.MAXNUMBER
AND( NUMBERTYPE = 'even' OR NUMBERTYPE = 'mixed');
DBMS_OUTPUT.PUT_LINE(test3);

但是,它不会返回任何内容,而是返回此

1059AJ

这是有效的邮政编码。它不应该这样做。

如果我要将邮政编码放在''这标志着它实际上没有任何回报。

SELECT P.POSTCODE INTO test4
FROM POSTCODE P
WHERE P.POSTCODE = UPPER('1059NJ')
AND P.CITY = INITCAP(LOWER('Amsterdam'))
AND P.STREET = INITCAP(LOWER('Aalsmeerweg'))
AND 14 BETWEEN P.MINNUMBER AND P.MAXNUMBER
AND( NUMBERTYPE = 'even' OR NUMBERTYPE = 'mixed');
DBMS_OUTPUT.PUT_LINE(test4);

这是Oracle的错误吗?

1 个答案:

答案 0 :(得分:4)

正如Llama先生所暗示,这是一个范围问题。在您的SQL语句中,普通postcode首先被解释为列名,并且因为有这样的列被使用。缺少别名限定符(p.)不会排除从该表中获取的值,也不会提升在列名称上方使用的局部变量。所以你真的在说:

WHERE P.POSTCODE = UPPER(p.postcode)

...这不是你想要的,并且意味着对于任何大写值,该子句将始终评估为true。

From the documentation

  

如果SQL语句引用既属于列又属于局部变量或形式参数的名称,则列名优先。

最简单的答案是重命名本地变量,并且通常会有一个强制执行此操作的命名约定;例如,使用p_为形式参数添加前缀,使用l_等添加局部变量

如果这是在命名块中,您还可以使用该名称为变量添加前缀;因此,如果您的函数被调用IsPostcodeValid,那么您可以这样做:

WHERE P.POSTCODE = UPPER(IsPostCodeValid.postcode)

命名约定更简单,更简洁,更清晰(IMO),但如果需要,您可以随时将两者结合使用,并引用IsValidPostcode.p_postcode以获得额外的明确性......

相关问题