2017-10-28 146 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查询中调用,这是您可能想要实现的。