2014-01-24 35 views
0

我遇到了一個奇怪的場景,其中to_number函數無法將一個數據庫中的字符串數據類型列中存儲的數字轉換爲另一個數據庫中的數據。to_number函數的Oracle數據類型轉換問題

所以,爲了排除所有可能的情況,如額外的空格,空值,垃圾等,我只選擇了一個單一的和在列上應用to_number函數,我完全不是將數字保存爲字符串的最佳實踐。

有趣的是,查詢在一個數據庫中執行得很好,但在其他數據庫中執行得很好。

下面的查詢在開發中運行良好,但在測試數據庫中運行良好。

select column_name 
from table_name 
where to_number(column_name) = 1618 

此外,當我在測試中運行以下查詢時,我得到的結果與任何錯誤。

select to_number(column_name) from table_name 

當我將to_number函數移動到where子句時,即我收到無效數字錯誤時。

有什麼想法?

謝謝...

+1

那麼,你的表中有非數字值。您的「where」子句中的To_number將執行全表掃描。任何無效值都會引發錯誤。 – OldProgrammer

+0

感謝您的快速回復,但是當我執行查詢'select_name(column_name)from table_name';它給結果。是不是在做全表掃描呢?我很困惑:( – user1751356

+0

是的,那麼在表格中不能有無效值,因爲你沒有向我們展示任何輸入或輸出數據,所以不能做出任何決定,下面是一個簡單的[ SqlFiddle](http://sqlfiddle.com/#!4/7b37e/1)證明錯誤 – OldProgrammer

回答

2

的問題是幾乎可以肯定的是在拋出一個錯誤的數據庫,您具有無法轉換爲數字的字符串值至少一行。找到該行的最簡單的方法通常是這樣做

CREATE FUNCTION is_number(p_str IN VARCHAR2) 
    RETURN VARCHAR2 
IS 
    l_num NUMBER; 
BEGIN 
    l_num := to_number(p_str); 
    RETURN 'Yes'; 
EXCEPTION 
    WHEN others 
    THEN 
    RETURN 'No'; 
END; 

然後

SELECT column_name 
    FROM table_name 
WHERE is_number(column_name) = 'No'; 

至於爲什麼

SELECT to_number(column_name) 
    FROM table_name 

的作品,你確定你是取每一行?當您運行查詢並且等待用戶在數據庫繼續執行查詢之前請求更多數據時,大多數工具只會獲取第一行,例如50行。假設無效數據在第10,001行,Oracle會高興地成功返回前10,000行,然後在請求獲取第10,001行時發出錯誤。

+0

我在數據庫中創建了一個備份表,我有這個問題並將相同的數據加載到備份表中。當我在備份表上運行相同的查詢時,我得到查詢結果,因爲當我在原始表上運行相同的查詢時,它會顯示無效的數字。所以,我看着這兩個表的執行計劃,就在那裏獲取結果表,其中作爲有問題的表說:從表中的行被訪問使用ROWID從全球拿到「是由select語句返回的行」 (交叉分區)索引「。兩者都有不同的成本,字節,基數。是因爲統計數據嗎? – user1751356

+0

絕對不是數據問題。 – user1751356

+0

@ user1751356 - 這是一個數據問題。如果你真正的查詢比你貼什麼更復雜的問題是,一些計劃將導致甲骨文看看無效數據的行並嘗試將其轉換爲數字,而其他計劃導致甲骨文在應用之前排除那些行' to_number'。您將需要解決數據問題,而不是試圖確保您獲得的任何計劃以不會產生錯誤的順序應用謂詞。 –