oracle 如何将LONG转换为VARCHAR2 inline

3z6pesqy  于 2023-05-28  发布在  Oracle
关注(0)|答案(4)|浏览(413)

背景:ALL_IND_EXPRESSIONS有列

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:不一致的数据类型:预期的数字得到了长

DBFiddle Demo

备注:

  • 它必须是自包含查询
  • 没有中间对象(创建表/视图不是一个选项)。
  • PL/SQL block
  • DBMS_METADATA.GET_DDL(实际情况并非如此)
  • WITH FUNCTION子句作为最后手段

是否可以将内置函数从LONG转换为VARCHAR2

编辑TL;DR:

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

hts6caw31#

您可以使用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.
44u64gxh

44u64gxh2#

使用WITH FUNCTIONConverting Long to Varchar2的方法,但它仍然有点丑陋和过于复杂。

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';

db<>fiddle demo

我相信应该有更优雅的方式来实现它。

t5fffqht

t5fffqht3#

正如OracleMaven自己所说,由于遗留原因,不可能将SUBSTR a LONG内联到VARCHAR2。AskTom link
在这个other link上,你会找到方法用一个过程甚至一个函数来完成它,如果LONG比32k LONG短的话。
这个函数可以在以后的SELECT查询中调用,这是您可能想要实现的。

g2ieeal7

g2ieeal74#

处理long的最好方法是:1)创建一个LOB类型的临时表(例如2)使用oracle唯一允许的语法:“TO_LOB将long_column列中的LONG或LONG RAW值转换为LOB值。您只能将此函数应用于LONG或LONGRAW列,并且只能应用于INSERT语句中的子查询的选择列表中。”3)利用临时表来完成您的工作

相关问题