web-dev-qa-db-fra.com

Comment convertir LONG en VARCHAR2 inline

Arrière-plan: ALL_IND_EXPRESSIONS has column

COLUMN_EXPRESSION   LONG   Function-based index expression defining the column

Je sais que LONG est obsolète. J'ai besoin d'écrire quelque chose comme (ou faire d'autres opérations de texte):

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: Types de données incohérents: NUMBER attendu LONG

DBFiddle Demo

Remarques:

  • il doit être une requête autonome
  • pas d'objets intermédiaires (la création de table/vue n'est pas une option).
  • non PL/SQL block
  • DBMS_METADATA.GET_DDL (ce n'est pas le cas)
  • Clause WITH FUNCTION en dernier recours

Est-il possible de transtyper/convertir/utiliser la fonction intégrée de LONG à VARCHAR2?

EDIT TL; DR:

SELECT column_expression || 'a'  -- convert to working code
FROM all_ind_expressions;
8
Lukasz Szozda

Vous pouvez utiliser XML sauf si les expressions contiennent quelque chose qui peut freiner l'analyse 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.
6
Dr Y Wit

Comme indiqué par les experts Oracle eux-mêmes, il n’est pas possible, pour des raisons historiques, d’insérer SUBSTR en LONGUE sur un VARCHAR2. Lien AskTom .

Sur ce lien other , vous trouverez des moyens de le faire avec une procédure et même avec une fonction si le paramètre LONG est inférieur à 32k LONG. 

Et cette fonction peut être appelée ultérieurement dans une requête SELECT, ce que vous souhaiterez peut-être atteindre.

2
hi olaf

Utiliser WITH FUNCTION et approcher de Conversion de Long en Varchar2 mais ça reste quand même moche et trop compliqué.

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

Question:

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

Je crois qu'il devrait y avoir un moyen plus élégant d'y parvenir.

2
Lukasz Szozda