Tokenizer - Percorrer string c/ campos sep. por ";"

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
  

Mensagemem Qua, 08 Fev 2006 2:25 pm

Boa tarde!!

Estou lendo uma planilha do excel no forms, com PL/SQL usando o TEXT_IO. Cada linha possui os campos que estão separador por ";", sendo que que tenho que pegar cada um desses campos e jogar numa variável. Acredito que alguém já deve ter feito isso, ou algo parecido, será que alguém poderia me dar uma dica????

ps: eu sei que com o SqlLoader é muito fácil, até já fiz, mais nesse caso tem q ser assim mesmo, na mão!

Obrigado pela atenção!!
Filipe_Geissler
Localização: Canoas - RS

Mensagemem Qua, 08 Fev 2006 3:30 pm

Eu tenho uma rotina interessante, mas acho que não se aplica ao seu caso. Essa rotina é mais util na passagem de parametros quando não se sabe o número de parametros de entrada...

Dá uma olhada:

Código: Selecionar todos
set ver off
def Del='@'
def String="@0@11@222@3333@44444@555555@6666666@77777777@888888888"

select
Rownum Row#,
SUBSTR(A.Str||'&Del'
, INSTR(A.Str||'&Del' , '&Del', 1, Rownum ) +1
, INSTR(A.Str||'&Del' , '&Del', 1, Rownum+1)
-INSTR(A.Str||'&Del' , '&Del', 1, Rownum ) -1
) Token
From
(
select
'&String' Str
from dual
)
A,
all_objects B
where
Rownum< length(A.Str)-length(REPLACE(A.Str,'&Del'))+1
;


ROW#       TOKEN
---------- -------------------------------------------------------
1          0
2          11
3          222
4          3333
5          44444
6          555555
7          6666666
8          77777777
9          888888888



Creio que você conseguirá com INSTR fazer essa sua... coloca um LOOP e vai pegando o SUBSTR entre um ; e outro...
:-o
dr_gori
Localização: Portland, OR USA

Thomas F. G

Você já respondeu a dúvida de alguém hoje?
http://glufke.net/oracle/search.php?search_id=unanswered

Mensagemem Qui, 09 Fev 2006 7:40 am

Consegui:

Código: Selecionar todos
begin
   
   in_file := Text_IO.Fopen(filename, 'r');
   -- loop para percorrer todas a linhas do arquivo
   LOOP
    begin
       Text_IO.Get_Line(in_file, linebuf);
       i := 0;
       numseparador := 1;
       aux := null;
       -- for para percorrer a linha caracter à caracter
         for i in 1..length(linebuf) loop
          caracter := ( substr(linebuf, i, 1));
          -- cada vez que achar o separador ";", separa o campo
          if caracter = ';' then
             if numseparador = 1 then
                ano := aux;
             elsif numseparador = 2 then
                mês := aux;
             elsif numseparador = 3 then
                pv := aux;
             elsif numseparador = 4 then
                valor_fat := aux;
             end if;
             -- incrementa o separador, que vai indicar o proximo campo
             numseparador := numseparador + 1;
             aux := null;             
          -- se não achar o separador, vai montando o campo ate achar o separador
          else
             aux := aux || caracter;
          end if;               
       end loop;
       message(ano || ' - ' || mês || ' - ' || pv || ' - ' || valor_fat);
       -- validações aqui...
      exception
        when no_data_found then
          Text_IO.Fclose(in_file);
          exit;
      end;
   END LOOP;
   
end;


Esse codigo lê o arquivo linha a e percorre a linha caracter a caracter até achar o ";", quando acha o ";" joga a string montada em "aux" na variável...
Funcionou muito bem. Postei aqui para deixar como consulta para outra pessoa!!
Qualquer dúvida é só falar!!!

falow
Filipe_Geissler
Localização: Canoas - RS

Mensagemem Qua, 22 Fev 2006 7:22 am

Para quem gosta de utilizar pl/table ai vai..

Código: Selecionar todos
/********************************************************************************************/
  /* Rotina responsável em separar "cargas" de dados que utilizam um separador em um "array"  */
  /********************************************************************************************/
  procedure prc_separa_texto( pTexto in varchar2, pSeparador in varchar2 default null ) is
    --
    pSeparador varchar2(1);
    --
    vContador number := 1;
     vInicio   number := 1;
     vFim      number := 0;
     --
     type tG_Array_Texto is table of varchar2(4000) index by binary_integer;
    vG_Texto_Separado tG_Array_Texto;
    --
   begin
     --
     loop
       --
       vFim := instr( pTexto, pSeparador, 1, vContador );
       --
       exit when vFim = 0;
       --
       vG_Texto_Separado(vContador) := substr( pTexto, vInicio, vFim - vInicio );
       --
       vInicio   := vFim      + 1;
       vContador := vContador + 1;
       --
     end loop;
    --
  end;

8)
leobbg
Localização: PORTO ALEGRE - RS

Leo BBG Consultor Oracle

Mensagemem Qua, 21 Mai 2008 5:01 pm

Outra forma de "tokenizar".
É necessário a criação do type TP_VARCHAR2 com o comando abaixo:
Código: Selecionar todos
CREATE TYPE TP_VARCHAR2 AS TABLE OF VARCHAR2(2000)


Código: Selecionar todos
CREATE OR REPLACE FUNCTION FNC_TOKENIZER(P_STRING    IN VARCHAR2,
                                         P_SEPARADOR IN VARCHAR2)
   RETURN TP_VARCHAR2 PIPELINED IS
   l_string LONG DEFAULT p_string || p_separador;
   n        NUMBER;
   /*----------------------------------------------------------------------*/
   /* Nome : FNC_PHW_TOKENIZER                                             */
   /* Descrição : Função para separação, em linhas diferentes, de valo-    */
   /* res de uma lista que utilize algum tipo de separador                 */
   /* Ex.: "A, B, C", separa cada letra num linha diferente                */
   /* Utilização:                                                          */
   /* select column_value valor from TABLE(fnc_tokenizer('A,B,C',','))     */
   /* Autor : Getulio Holtz (TechnoCorp)                                   */
   /* Data : 27 de Setembro de 2006                                        */
   /* É necessário a criação do tipo TP_VARCHAR2 com o comando abaixo:     */
   /* CREATE TYPE TP_VARCHAR2 AS TABLE OF VARCHAR2(2000)                   */
   /*----------------------------------------------------------------------*/


BEGIN
   LOOP
      EXIT WHEN nvl(l_string,' ') = ' ';
      n := instr(l_string,
                 p_separador);
      dbms_output.put_line(n);
      PIPE ROW(ltrim(rtrim(substr(l_string,
                                  1,
                                  n - 1))));
      l_string := substr(l_string,
                         n + 1);
   END LOOP;
   RETURN;
END FNC_TOKENIZER;
/
dr_gori
Localização: Portland, OR USA

Thomas F. G

Você já respondeu a dúvida de alguém hoje?
http://glufke.net/oracle/search.php?search_id=unanswered

Mensagemem Sex, 05 Out 2012 10:39 am

Aqui vai mais uma forma de tokenizar, contribuiçao do Paulo Diniz (Mato Grosso do Sul)
Isso usa expressões regulares e CONNECT BY :-)

Código: Selecionar todos
select REGEXP_SUBSTR(str, exp, 1, level) lista
from (select 'paulo@email.com;thomas@email.com' str, '[^;]+' exp
      from dual)
connect by REGEXP_SUBSTR(str, exp, 1, level) is not null


Saida:
Código: Selecionar todos
LISTA
--------------------------------
paulo@email.com
thomas@email.com


Tem um documento dele que explica como fazer o contrário disso, ou seja: pegar diversas linhas e agrupar em uma so, delimitado por um caracter. (utilizando a função nativa do 11g chamado LISTAGG).
https://docs.google.com/file/d/0B7CiEAx ... t?hl=en_US
ou
http://www.linkedin.com/groups/Converte ... RITM-title
dr_gori
Localização: Portland, OR USA

Thomas F. G

Você já respondeu a dúvida de alguém hoje?
http://glufke.net/oracle/search.php?search_id=unanswered


  • Veja também
    Respostas
    ExibiÇões
    Última mensagem


      Voltar para PL/SQL

      Quem está online

      Usuários navegando neste fórum: Nenhum usuário registrado e 5 visitantes