2017-10-28 148 views
5

背景:ALL_IND_EXPRESSIONS有列如何LONG轉換爲VARCHAR2直列

COLUMN_EXPRESSION LONG Function-based index expression defining the column 

我知道LONG已被棄用。我需要寫類似(或做其他的文本操作):

SELECT 
    REPLACE(REPLACE(REPLACE(
    q'{ALTER INDEX "<index_owner>"."<index_name>" ON ... (<column_expression>)}' 
    ,'<index_owner>', index_owner) 
    ,'<index_name>', index_name) 
    ,'<column_expression>', column_expression) AS result 
FROM all_ind_expressions; 

ORA-00932:不一致的數據類型:預期數量有LONG

DBFiddle Demo

備註:

  • 它必須是自包含查詢
  • 沒有中間對象(創建表/視圖不是一個選項)。
  • 沒有PL/SQL block
  • DBMS_METADATA.GET_DDL(這是不是這樣)
  • WITH FUNCTION clause作爲最後手段

是否有可能投/轉換/使用內置函數從LONGVARCHAR2

編輯TL; DR:

SELECT column_expression || 'a' -- convert to working code 
FROM all_ind_expressions; 
+0

可能重複[Converting Long to Varchar2](https://stackoverflow.com/questions/31004844/converting-long-to-varchar2) –

+0

@CyrilleMODIANO提到的答案可能會有所幫助。 '使用單個語句立即從long轉換爲varchar2是不可能的,只要有一定的限制即可。「官方文檔的任何鏈接? – lad2025

回答

4

您可以使用XML,除非表達式包含可以制止XML解析的內容。

select * 
    from xmltable(
      '/ROWSET/ROW' 
      passing (select dbms_xmlgen.getxmltype('select * from all_ind_expressions 
                where index_name = ''XDB$COMPLEX_TYPE_AK''') 
        from dual) 
      columns index_owner varchar2(30) path 'INDEX_OWNER', 
        index_name varchar2(30) path 'INDEX_NAME', 
        table_owner varchar2(30) path 'TABLE_OWNER', 
        table_name varchar2(30) path 'TABLE_NAME', 
        column_expression varchar2(4000) path 'COLUMN_EXPRESSION') 

INDEX_OWNER  INDEX_NAME   TABLE_OWNER  TABLE_NAME   COLUMN_EXPRESSION     
--------------- -------------------- --------------- -------------------- ----------------------------------- 
XDB    XDB$COMPLEX_TYPE_AK XDB    XDB$COMPLEX_TYPE  SYS_OP_R2O("XMLDATA"."ALL_KID")  
1 row selected. 
+0

感謝您的想法,我會測試它:)我希望它能適用於我所有的情況(我不想爲非可分析的XML創建例外) – lad2025

2

運用Converting Long to Varchar2WITH FUNCTION和方法,但仍是莫名其妙醜陋和過於複雜。

CREATE TABLE TEST(Z INT); 
CREATE INDEX IF_DOUBLE_TEST_Z ON TEST(Z*2); 

查詢:

WITH FUNCTION s_convert(pindex_owner VARCHAR2, pindex_name VARCHAR2, 
         ptable_owner VARCHAR2, ptable_name VARCHAR2) 
       RETURN VARCHAR2 
AS 
    VAR1 LONG; 
    VAR2 VARCHAR2(4000); 
BEGIN 
    SELECT column_expression 
    INTO VAR1 
    FROM all_ind_expressions 
    WHERE index_owner = pindex_owner AND index_name = pindex_name 
    AND table_owner = ptable_owner AND table_name = ptable_name 
    AND column_position = 1; -- only one column indexes 

    VAR2 := SUBSTR(VAR1, 1, 4000); 
    RETURN VAR2; 
END; 
SELECT aie.*, 
    REPLACE(REPLACE(REPLACE(
    q'{ALTER INDEX "<index_owner>"."<index_name>" ON ... (<column_expression>)}' 
    ,'<index_owner>', index_owner) 
    ,'<index_name>', index_name) 
    ,'<column_expression>', 
     s_convert(index_owner, index_name, table_owner, table_name)) AS result 
FROM all_ind_expressions aie 
WHERE TABLE_NAME='TEST'; 

我認爲,應該有更優雅的方式來實現它。

2

以自己的聲明由Oracle專家,對遺留的原因,不可能長期內聯SUBSTR一到VARCHAR2。 AskTom link

在這個other link你會找到方法來做到這一點,如果LONG比32k LONG更短,甚至可以使用函數。

而且這個函數可以稍後在SELECT查詢中調用,這是您可能想要實現的。