2011-03-04 62 views
16

Estoy en un aprieto: me han pedido que tome comentarios comenzando con una cadena específica de una base de datos, y separe el resultado en columnas separadas.Dividir varchar en columnas separadas en Oracle

Por ejemplo - si el valor devuelto es la siguiente:

COLUMN_ONE 
-------------------- 
'D7ERROR username' 

El retorno tiene que ser:

COL_ONE COL_TWO 
-------------------- 
D7ERROR username 

¿Es incluso posible definir columnas una vez que el conjunto de resultados se ha estructurado simplemente por el bien de dividir una cuerda en dos?

Respuesta

34

depende de la consistencia de los datos - asumiendo un solo espacio es el separador entre lo que desea que aparezca en la columna uno contra dos:

SELECT SUBSTR(t.column_one, 1, INSTR(t.column_one, ' ')-1) AS col_one, 
     SUBSTR(t.column_one, INSTR(t.column_one, ' ')+1) AS col_two 
    FROM YOUR_TABLE t 

Oracle 10g + tiene soporte de expresiones regulares, lo que permite una mayor flexibilidad en función de la situación que necesitas resolver También cuenta con un método de expresiones regulares subcadena ...

Referencia:

+2

Detalle menor ... Esto incluirá el espacio como parte de la primera columna en la salida. Es probable que desee que sea SUBSTR (t.column_one, 1, INSTR (t.column_one, '') -1) – Craig

+1

@Craig: corregido - ¡thx! –

+0

Agradable. Gracias por la ayuda. – ryebr3ad

25

Con REGEXP_SUBSTR es tan simple como:

SELECT REGEXP_SUBSTR(t.column_one, '[^ ]+', 1, 1) col_one, 
     REGEXP_SUBSTR(t.column_one, '[^ ]+', 1, 2) col_two 
FROM YOUR_TABLE t; 
+0

Esto es muy útil, pero solo funciona con un char (char del espacio en blanco). ¿Cómo se puede modificar esto para que funcione con más de un carácter, uno que se garantice que no existe en el contenido (por ejemplo, '' -> '~~' u otra cosa inusual)? –

+0

Sé que estoy resucitando una vieja pregunta, @CharlesHenry - ¿Lo intentaste? simplemente reemplace el espacio con ~~ 'seleccione regexp_substr ('123 ~~ 45,6,7', '[^ ~~] +', 1, 1), regexp_substr ('123 ~~ 45,6,7', ' [^ ~~] + ', 1, 2) desde dual' –

+0

Terminé usando sentencias CASE y NVL para ponerlo en funcionamiento. Funciona ** mucho ** más rápido que regex ya que estas funciones son una parte central de Oracle. –

3

forma sencilla es para convertir a la columna

SELECT COLUMN_VALUE FROM TABLE (SPLIT ('19869,19572,19223,18898,10155,')) 

CREATE TYPE split_tbl as TABLE OF VARCHAR2(32767); 

CREATE OR REPLACE FUNCTION split (p_list VARCHAR2, p_del VARCHAR2 := ',') 
    RETURN split_tbl 
    PIPELINED IS 
    l_idx PLS_INTEGER; 
    l_list VARCHAR2 (32767) := p_list; 
    l_value VARCHAR2 (32767); 
BEGIN 
    LOOP 
     l_idx := INSTR (l_list, p_del); 

     IF l_idx > 0 THEN 
     PIPE ROW (SUBSTR (l_list, 1, l_idx - 1)); 
     l_list := SUBSTR (l_list, l_idx + LENGTH (p_del)); 
     ELSE 
     PIPE ROW (l_list); 
     EXIT; 
     END IF; 
    END LOOP; 

    RETURN; 
END split; 
+0

Si bien sería posible crear una función canalizada que funcione de esta manera, 'split' no es una función incorporada en Oracle. – Allan

+0

Allan, aquí están los detalles de la función en Oracle, enlace http://docs.oracle.com/cd/E13292_01/pt849pbr0/eng/psbooks/tpcl/chapter.htm?File=tpcl/htm/tpcl02.htm – bluesky

+0

Esa es la documentación para Peopletools, no el RDBMS de Oracle. – Allan

Cuestiones relacionadas