2015-06-11 35 views
2

我試圖檢查郵政編碼是否有效。示例代碼中的郵政編碼無效。所以它不應該返回任何值。Bug UPPER(變量)

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錯誤嗎?

+3

嘗試在輸入表上命名'postcode'變量而不是列名。 –

+0

這實際上有用,非常感謝!我一直堅持了幾個小時。 –

+0

不相關,但爲什麼'initcap(lower())'比僅僅'initcap()'大? 'lower()'似乎有點無意義。即使你沒有真正的字符串文字。 –

回答

4

正如Llama先生暗示的那樣,這是一個範圍問題。在你的SQL語句中,普通的postcode首先被解釋爲列名,並且因爲有這樣的列被使用。缺少別名限定符(p.)並不排除從該表中獲取值,或者提升要在列名稱上方使用的局部變量。所以你真的在說:

WHERE P.POSTCODE = UPPER(p.postcode) 

......這不是你想要的,並且意味着子句總是對任何大寫值計算爲真。

From the documentation

如果SQL語句引用同時屬於列以及局部變量或形式參數的名稱,然後列名優先。

最簡單的答案是重命名您的本地變量,並且通常有一個命名約定來強制執行此操作;例如使用p_作爲形式參數的前綴,使用l_的局部變量等。

如果這是在一個命名塊中,您也可以在該變量前面加上該名稱;所以如果你的函數調用IsPostcodeValid那麼你可以做:

WHERE P.POSTCODE = UPPER(IsPostCodeValid.postcode) 

的命名慣例是更簡單,更短和更清晰的(IMO),但你總是可以結合兩種,如果你想要的,是指IsValidPostcode.p_postcode額外的明確性。 ..