2012-05-22 34 views
3

我的問題是:是否有UTL_MATCH般的功能,其與CLOB而非VARCHAR2工作?UTL_MATCH的功能,可以與CLOB工作

我的具體問題是:我在Oracle數據庫上。我有一堆預先編寫的查詢,它與Domo CenterView接口。查詢的變量由${variableName}定義。我需要重寫這些查詢。我沒有編寫原始代碼,因此我沒有弄清楚變量的優點是什麼,我想用應用程序運行查詢,並從V$SQL獲取查詢內容。

所以我的解決方案是:做一個UTL_MATCH查詢與變量的東西在它和V$SQL.SQL_FULLTEXT。但是,UTL_MATCH限制爲VARCHAR2,而V$SQL.SQL_FULLTEXT的數據類型爲CLOB。所以,這就是爲什麼我要找一個類似UTL_MATCH的函數,它可以與CLOB數據類型一起使用。

如何完成此任何其他技巧是值得歡迎的。謝謝!

編輯,關於提示。如果您對如何做到這一點有了更好的瞭解,那麼讓我告訴您一些我掌握的信息。我有大約100個查詢,他們都在Excel電子表格中(其中有${variableName})。所以我可以很容易地使用Excel爲我寫一個查詢。我希望能夠將所有這些查詢結合在一起並將輸出複製到另一個表單中。無論如何,如果你認爲有更好的方法來做到這一點,那也許會有幫助。

一個例子:比方說,我有一個從多摩以下查詢:

select department.dept_name 
from department 
where department.id = '${selectedDepartmentId}' 
; 

我想打電話給這樣的事情:

select v.sql_fulltext 
from v$sql v 
where utl_match.jaro_winkler_similarity(v.sql_fulltext, 
'select department.dept_name 
from department 
where department.id = ''${selectedDepartmentId}''') > 90 
; 

而得到這樣的回報:

SQL_FULLTEXT 
------------------------------------------ 
select department.dept_name 
from department 
where department.id = '154' 

我已經tr了ied:

我嘗試子串串並將其轉換爲varchar。我真的很希望這會起作用,但它給了我一個錯誤。下面的代碼:

select v.sql_fulltext 
from v$sql v 
where utl_match.jaro_winkler_similarity(cast(substr (v.sql_fulltext, 0, 4000) as varchar2 (4000)), 
'select department.dept_name 
from department 
where department.id = ''${selectedDepartmentId}''') > 90 
; 

而這裏的錯誤:

ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 8000, maximum: 4000)

但是,如果我運行這個它工作正常:

select cast(substr(v.sql_fulltext, 0, 4000) as varchar2 (4000)) 
from v$sql v 
; 

所以我不知道是什麼問題是鑄造子串...

回答

1

我結束了創建一個自定義的功能。代碼如下:

CREATE OR REPLACE function match_clob(clob_1 clob, clob_2 clob) return number as 

similar number := 0; 
sec_similar number := 0; 
sections number := 0; 
max_length number := 3949; 
length_1 number; 
length_2 number; 
vchar_1 varchar2 (3950); 
vchar_2 varchar2 (3950); 

begin 
    length_1 := length(clob_1); 
    length_2 := length(clob_2); 
    --dbms_output.put_line('length_1: '||length_1); 
    --dbms_output.put_line('length_2: '||length_2); 
    IF length_1 > max_length or length_2 > max_length THEN 

    FOR x IN 1 .. ceil(length_1/max_length) LOOP 

     --dbms_output.put_line('((x-1)*max_length) + 1'||(x-1)||' * '||max_length||' = '||(((x-1)*max_length) + 1)); 

     vchar_1 := substr(clob_1, ((x-1)*max_length) + 1, max_length); 
     vchar_2 := substr(clob_2, ((x-1)*max_length) + 1, max_length); 

--  dbms_output.put_line('Section '||sections||' vchar_1: '||vchar_1||' ==> vchar_2: '||vchar_2); 

     sec_similar := UTL_MATCH.JARO_WINKLER_SIMILARITY(vchar_1, vchar_2); 

     --dbms_output.put_line('sec_similar: '||sec_similar); 

     similar := similar + sec_similar; 
     sections := sections + 1; 

    END LOOP; 

    --dbms_output.put_line('Similar: '||similar||' ==> Sections: '||sections); 
    similar := similar/sections; 

    ELSE 
    similar := UTL_MATCH.JARO_WINKLER_SIMILARITY(clob_1,clob_2); 
    END IF; 
    --dbms_output.put_line('Overall Similar: '||similar); 
    return(similar); 
end; 
/
+0

您應該可以將max_length,vchar_1和vchar_2設置爲32767.對於SQL和PL/SQL,最大字符限制是不同的。 –

+0

好點,我會給它一個鏡頭,並更新方法。謝謝 – kentcdodds

1

UTL_MATCH是comp用字符串來檢查兩個字符串的相似程度。它的功能評估字符串並返回分數。所以你要得到的是一個數字,表示(比如說)你需要將${variableName}變成「Farmville」或「StackOveflow」。

你不會得到的是實際的區別:這兩個文本字符串是相同的,除了在偏移量123處,它用「Farmville」代替${variableName}

把它像這樣表明一種替代方法。使用INSTR()SUBSTR()在您的Domo CenterView查詢中找到${variableName}的實例,並使用這些偏移量標識v$sql.fulltext等效項中的不同文本。您可以使用PL/SQL中的CLOB在DBMS_LOB package中執行此操作。

+0

我原來的問題可能不夠清楚。但是,您的答案可能會用作替代方法。我的意思是,雖然我只想找到已經在服務器上運行的類似於domo查詢的查詢。我不是試圖用實際存在的變量替換變量,我只是試圖找到那個查詢,因爲它實際上是運行的,只是使用它。我不知道我現在是否有任何意義,但我會考慮你提供的鏈接。謝謝。 – kentcdodds

+0

遠不是「不夠清楚」,你提到的UTL_MATCH的原始問題肯定是誤導性的。 – APC

+1

真的嗎?我認爲這很清楚。我不在乎找到變量的位置並替換它們或任何東西。我只想找到與具有正在工作的查詢重寫的變量相似的查詢。你如何建議我改進這個問題? – kentcdodds

1

如果你想搜索的文本長度爲< = 32767,那麼你可以轉換到CLOB使用VARCHAR2DBMS_LOB.SUBSTR

select v.sql_fulltext 
from v$sql v 
where utl_match.jaro_winkler_similarity(dbms_lob.substr(v.sql_fulltext), 'select department.dept_name from department where department.id = ''${selectedDepartmentId}''') > 90 ; 
+0

剛剛嘗試過,它給了我以下錯誤:'ORA-06502:PL/SQL:數字或值錯誤:字符串緩衝區太小' – kentcdodds

+0

這可以工作,但您需要在PL/SQL中使用它上下文以允許VARCHAR2使用32767個字符。您需要將值提取到CLOB中,將其轉換或轉換爲VARCHAR2,然後遍歷結果並調用UTL_MATCH包。 –