2012-07-10 78 views
1

基於10g中表達式的結果創建派生列是否有任何方法?基於表達式結果的Oracle派生列

具體來說,我繼承了一個表,其中包含varchar2字段中的字符數據和數字數據。顯然,在嘗試進行連接時不會導致頭痛,因爲當Oracle重新對我的查詢使用to_number()進行重新排序時,我會不斷得到「無效數字」錯誤。所以,我想要做的是創建一個派生列,如果原始列的值是數值,那麼它將有一個值,如果不是,則在NULL中使用它,而不是混合類型的字段。

請注意,我試圖在查詢中執行此操作,而不是在過程/函數中執行此操作。

這樣的事情可能嗎?

回答

2

你可以來在10g中最接近的是一個基於函數的索引。像

CREATE OR REPLACE FUNCTION my_to_number(p_str IN VARCHAR2) 
    RETURN NUMBER 
    DETERMINISTIC 
IS 
    l_num NUMBER; 
BEGIN 
    l_num := to_number(p_str); 
    RETURN l_num; 
EXCEPTION 
    WHEN OTHERS THEN 
    RETURN NULL; 
END; 

CREATE INDEX idx_derived_column 
    ON table_name(my_to_number(column_name)); 

某事,這通常需要一個函數來創建,並在查詢中引用而基於函數的索引預先計算的結果,這樣你就不會實際調用在運行時的功能。如果你真的想避免這個函數,你也可以在CASE聲明中創建索引,然後在查詢中引用相同的CASE語句,但這似乎會使情況複雜化,而不是簡單化。

1

可以使用正則表達式:

select * from table where varchar_field not like '%[0-9]%'; 
+1

我會還建議將[正則表達式](http://psoug.org/reference/regexp.html)放入子查詢中,然後加入這些子查詢。注意兩件事情,(1)最好是將「一列全部統治」分開,並將該表分成兩列,以避免這些問題(數字到數字,文本到文本)。 (2)如果你有一個像'12 abc 34 def'這樣的列,你最好確保你的regExp採用了你想要的阿爾法和你想要的數字,但是我強烈建議修復這個表並且用#1 – Harrison 2012-07-10 15:40:23

+0

你不能很容易)決定在查詢中首先執行哪些子句。如果連接在過濾器之前執行,則會導致數字轉換錯誤。 – 2012-07-10 15:53:12

3

在Oracle 11g中,您可以定義virtual columns

ALTER TABLE mytable ADD (new_column GENERATED ALWAYS AS (CASE WHEN id ...)); 

在10g之前,我會建議使用一種觀點:

CREATE VIEW myview AS SELECT t.*, CASE WHEN ... END id_number FROM mytable; 

你甚至可以索引你與性能基於功能的索引表達式(只要你只使用SQL標準函數和確定性定製函數):

CREATE INDEX idx ON mytable (CASE WHEN ...);