Bom dia..
Estou com um problema pra resolver e gostaria de saber se alguém pode me ajudar..
Tenho um relatório, gerado em um arquivo texto por uma procedure. A linha da descrição (string) no arquivo-texto possui limite de 45 caracteres. Acontece de alguns textos virem maiores que isso então o arquivo-texto automaticamente "quebra" pra uma linha de baixo quando passa de 45 caracteres e assim por diante..
O problema é que quando exatamente na posição 45 do texto, cair no meio de uma palavra, metade desta palavra cai pra linha de baixo. (ex: PALAVRA, ficaria, PALA --> VRA iria pra linha de baixo), assim o texto fica meio desfigurado.
A idéia é quando cair em casos assim, eu mover a palavra inteira para a linha de baixo..
Estou tendo enormes dificuldades pra fazer isso acontecer, se alguém puder me ajudar..
Um abraço a todos..
Daniel Simoes, RJ..
Quebra de Linha em um texto
-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Só exibindo um pouco do código... senão não tem como saber como está implementado o programa que gera esse texto.
Daria para postá-lo aqui por favor?
Daria para postá-lo aqui por favor?
-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
Esse é o trecho que eu estava tentando modificar..
Mas não funciona..
Então eu fiz a seguinte rotina pra testar:
Mas mesmo assim ainda não está satisfatório...
IF MOD(LENGTH(vTEHISTLANC)/45,1) = 0
THEN vLOOPHISTORICO := TRUNC(LENGTH(vTEHISTLANC)/45);
ELSE vLOOPHISTORICO := TRUNC(LENGTH(vTEHISTLANC)/45)+1;
END IF;
vINDICE := 0;
WHILE vINDICE < vLOOPHISTORICO LOOP
vNULINHA := vNULINHA + 1;
vINDICE := vINDICE + 1;
IF vINDICE = 1 THEN
vCARACTERINICIO := vINDICE;
ELSE
vCARACTERINICIO := vCARACTERINICIO + 45;
END IF;
IF vINDICE <> vLOOPHISTORICO THEN
vVLLANCAUX :=0;
ELSE
vVLLANCAUX := vVLLANC;
END IF;
Então eu fiz a seguinte rotina pra testar:
declare
vTeste Varchar2(1000);
vSaida varchar2(1000);
vPosChar number(10);
vLoopCtrl number(10);
vLoop number(10);
vLastSpace number(10);
begin
vTeste := 'Daniel Simoes';
vPosChar := 1;
vLoopCtrl := 1;
vLoop := length(vTeste);
vLastSpace := 0;
-- Varre toda a linha
while (vLoopCtrl <= vLoop) loop
-- Armazerna a posição do último espaço
if substr(vTeste,vPosChar,1) = ' ' then
vLastSpace := vPosChar;
end if;
-- Verifica se pode fazer a quebra de linha
if (vPosChar = 10) and (vPosChar < vLoop) then
-- Testa para ver se o próximo caractere
-- faz parte da palavra
if substr(vTeste,vPosChar+1,1) <> ' ' then
-- Copia todo o conteudo até a última palavra válida
vSaida := substr(vSaida,1,vLastSpace);
dbms_output.put_line('Trecho Quebra: ' || vSaida);
-- Copia o trecho restante
vTeste := Substr(vTeste,vPosChar,Length(vTeste));
vSaida := '';
vPosChar := 1;
vLastSpace := 0;
end if;
end if;
vSaida := vSaida || substr(vTeste,vPosChar,1);
vPosChar := vPosChar + 1;
vLoopCtrl := vLoopCtrl + 1;
end loop;
dbms_output.put_line('Trecho Final: ' || vSaida);
end;
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Acho que dá para fazer algo assim:
Tem que testar melhor para ver se não tem algum bug de repente.
Falou!
SQL> set serveroutput on
SQL>
SQL> DECLARE
2 v_teste VARCHAR2(4000) := 'Daniel Simoes foi ao mercado comprar pão e leite.';
3 v_limite NUMBER := 10;
4 v_saida VARCHAR2(4000);
5 v_resto VARCHAR2(4000);
6 v_prox_trecho VARCHAR2(4000);
7 v_linha NUMBER := 0;
8 BEGIN
9 v_resto := v_teste;
10 LOOP
11 v_prox_trecho := regexp_substr(v_resto, '^[^ ]+\s*');
12 -- se for menor do que o tamanho máximo da linha
13 IF (nvl(length(rtrim(v_prox_trecho)), 0) + nvl(length(v_saida), 0) <= v_limite)
14 AND v_prox_trecho IS NOT NULL
15 THEN
16 v_resto := regexp_replace(v_resto, '^[^ ]+\s*');
17 v_saida := ltrim(v_saida || ' ') || rtrim(v_prox_trecho);
18 ELSE
19 v_linha := v_linha + 1;
20 dbms_output.put_line(v_linha || ' - ' || v_saida);
21 v_saida := rtrim(v_prox_trecho);
22 v_resto := regexp_replace(v_resto, '^[^ ]+\s*');
23 EXIT WHEN v_resto IS NULL;
24 END IF;
25 END LOOP;
26 END;
27 /
1 - Daniel
2 - Simoes foi
3 - ao mercado
4 - comprar pão
5 - e leite.
PL/SQL procedure successfully completed
SQL>
Falou!
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Achei um bug já... estava verificando errado no if:
SQL> set serveroutput on
SQL> DECLARE
2 v_teste VARCHAR2(4000) := 'Daniel Simoes foi ao mercado comprar pão e leite.';
3 v_limite NUMBER := 10;
4 v_saida VARCHAR2(4000);
5 v_resto VARCHAR2(4000);
6 v_prox_trecho VARCHAR2(4000);
7 v_linha NUMBER := 0;
8 BEGIN
9 v_resto := v_teste;
10 LOOP
11 v_prox_trecho := regexp_substr(v_resto, '^[^ ]+\s*');
12 -- se for menor do que o tamanho máximo da linha
13 IF (length(ltrim(v_saida || ' ') || rtrim(v_prox_trecho)) <= v_limite)
14 AND v_prox_trecho IS NOT NULL
15 THEN
16 v_resto := regexp_replace(v_resto, '^[^ ]+\s*');
17 v_saida := ltrim(v_saida || ' ') || rtrim(v_prox_trecho);
18 ELSE
19 v_linha := v_linha + 1;
20 dbms_output.put_line(v_linha || ' - ' || v_saida);
21 v_saida := rtrim(v_prox_trecho);
22 v_resto := regexp_replace(v_resto, '^[^ ]+\s*');
23 EXIT WHEN v_saida IS NULL;
24 END IF;
25 END LOOP;
26 END;
27 /
1 - Daniel
2 - Simoes foi
3 - ao mercado
4 - comprar
5 - pão e
6 - leite.
PL/SQL procedure successfully completed
-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
Ok!!
Vou verificar aqui e posto o resultado neste tópico..
Obrigado!!
Vou verificar aqui e posto o resultado neste tópico..
Obrigado!!
-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
Botei pra executar essa rotina mas deu o seguinte erro:
Relatório de erro:
ORA-06550: linha 11, coluna 24:
PLS-00201: o identificador 'REGEXP_SUBSTR' deve ser declarado
ORA-06550: linha 11, coluna 7:
PL/SQL: Statement ignored
ORA-06550: linha 16, coluna 20:
PLS-00201: o identificador 'REGEXP_REPLACE' deve ser declarado
ORA-06550: linha 16, coluna 9:
PL/SQL: Statement ignored
ORA-06550: linha 22, coluna 20:
PLS-00201: o identificador 'REGEXP_REPLACE' deve ser declarado
ORA-06550: linha 22, coluna 9:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Usei o SQL Developer..
Minha versão do oracle é a 10g, o que tem de errado??
att,
Daniel, RJ.
Relatório de erro:
ORA-06550: linha 11, coluna 24:
PLS-00201: o identificador 'REGEXP_SUBSTR' deve ser declarado
ORA-06550: linha 11, coluna 7:
PL/SQL: Statement ignored
ORA-06550: linha 16, coluna 20:
PLS-00201: o identificador 'REGEXP_REPLACE' deve ser declarado
ORA-06550: linha 16, coluna 9:
PL/SQL: Statement ignored
ORA-06550: linha 22, coluna 20:
PLS-00201: o identificador 'REGEXP_REPLACE' deve ser declarado
ORA-06550: linha 22, coluna 9:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Usei o SQL Developer..
Minha versão do oracle é a 10g, o que tem de errado??
att,
Daniel, RJ.
-
- Moderador
- Mensagens: 86
- Registrado em: Qua, 15 Mar 2006 2:46 pm
- Localização: São Paulo - SP
Paulo Chagas Filho
__________________
Analista Funcional / Desenvolvedor Oracle EBS
MSN - paulochagas@hotmail.com
Gtalk - pachafi@gmail.com
Skype - paulochagas
__________________
Analista Funcional / Desenvolvedor Oracle EBS
MSN - paulochagas@hotmail.com
Gtalk - pachafi@gmail.com
Skype - paulochagas
Creio que Funções com Expressões regulares só funcionam em versões do Oracle 10G ou mais recente
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Deve ser isso mesmo... seu Oracle é 9i?
Aí vai ter que fazer ums ginástica maior com instr() e substr(), procurando espaços.
Aí vai ter que fazer ums ginástica maior com instr() e substr(), procurando espaços.
-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
Galera, obrigado pelas dicas..
Consegui resolver o problema..
Mas tive problemas em executar o código que vocês me passaram justamente pelo fato do meu oracle ser o 9i.. :(
Então, dei uma estudada nos dois códigos (meu e de vocês) e verifiquei melhor, concluí que tinha alguns bugs pra resolverem que consegui corrigir no código abaixo:
Funcionou dessa forma:
1 Daniel
2 Simoes
3 foi ao
4 mercado
5 comprar
6 coisas
ps.: O que eu comentei como "NOVO" ao final da linha de código, são as alterações que fiz pra rotina funcionar...
Muito obrigado a todos pela ajuda... :D
Abraços!!!
att,
Daniel Simões, RJ..
Consegui resolver o problema..
Mas tive problemas em executar o código que vocês me passaram justamente pelo fato do meu oracle ser o 9i.. :(
Então, dei uma estudada nos dois códigos (meu e de vocês) e verifiquei melhor, concluí que tinha alguns bugs pra resolverem que consegui corrigir no código abaixo:
set serveroutput on
declare
vTeste Varchar2(1000);
vSaida varchar2(1000);
vPosChar number(10);
vLoopCtrl number(10);
vLoop number(10);
vLastSpace number(10);
vPosNova number(10); -- NOVO
begin
vTeste := 'Daniel Simoes foi ao mercado comprar coisas';
vPosChar := 1;
vLoopCtrl := 1;
vLoop := length(vTeste);
vLastSpace := 0;
vPosNova := 0; -- NOVO
-- Varre toda a linha
while (vLoopCtrl <= vLoop) loop
-- Armazerna a posição do último espaço
if substr(vTeste,vPosChar,1) = ' ' then
vLastSpace := vPosChar;
end if;
-- Verifica se pode fazer a quebra de linha
if (vPosChar = 10) and (vPosChar < vLoop) then
-- Testa para ver se o próximo caractere
-- faz parte da palavra
if substr(vTeste,vPosChar+1,1) <> ' ' then
-- Copia todo o conteudo até a última palavra válida
vSaida := substr(vSaida,1,vLastSpace);
dbms_output.put_line('Trecho Quebra: ' || vSaida);
vPosNova := vLastSpace; -- NOVO
-- Copia o trecho restante
vTeste := Substr(vTeste,vPosNova,Length(vTeste));
vSaida := '';
vPosChar := 1;
vLastSpace := 0;
vPosNova := 0; -- NOVO
vLoopCtrl := 0; -- NOVO
end if;
end if;
vSaida := vSaida || substr(vTeste,vPosChar,1);
vPosChar := vPosChar + 1;
vLoopCtrl := vLoopCtrl + 1;
end loop;
dbms_output.put_line('Trecho Final: ' || vSaida);
end;
1 Daniel
2 Simoes
3 foi ao
4 mercado
5 comprar
6 coisas
ps.: O que eu comentei como "NOVO" ao final da linha de código, são as alterações que fiz pra rotina funcionar...
Muito obrigado a todos pela ajuda... :D
Abraços!!!
att,
Daniel Simões, RJ..
-
- Rank: Estagiário Júnior
- Mensagens: 1
- Registrado em: Sex, 19 Nov 2010 9:45 am
- Localização: Curitiba
Olá pessoal,
Utilizo o forum de faz bastante tempo, e já me ajudou muito!
Para a pergunta do colega acima, tem uma solução um pouco mais simples.
Fico feliz por poder ajudar um pouco!
abraços!!

Utilizo o forum de faz bastante tempo, e já me ajudou muito!
Para a pergunta do colega acima, tem uma solução um pouco mais simples.
Fico feliz por poder ajudar um pouco!
abraços!!
SELECT Trim(SUBSTR('Daniel Simoes agora faz em uma linha somente',INSTR('Daniel Simoes agora faz em uma linha somente',' ',-1,1)))
FROM dual;

- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Olá LaraJacuniak,
Bem-vindo ao fórum como colaborador também
A dificuldade que o Daniel estava enfrentando era "formatar" a entrada, quebrando em linhas por um limite de largura de linha determinado.
Nesse sentido, fica um pouco mais complexo de resolver em SQL apenas. Creio que precisaria usar Connect By, With-Recursivo ou Model, mas sem expressões regulares é preferível resolvr com PL/SQL mesmo, pela complexidade excessiva do SQL.
Bem-vindo ao fórum como colaborador também

A dificuldade que o Daniel estava enfrentando era "formatar" a entrada, quebrando em linhas por um limite de largura de linha determinado.
Nesse sentido, fica um pouco mais complexo de resolver em SQL apenas. Creio que precisaria usar Connect By, With-Recursivo ou Model, mas sem expressões regulares é preferível resolvr com PL/SQL mesmo, pela complexidade excessiva do SQL.
-
- Rank: DBA Pleno
- Mensagens: 232
- Registrado em: Qui, 26 Nov 2009 1:05 pm
- Localização: SP
Ricardo H. Tajiri
Com a cláusula MODEL ficaria:
Com a saída:
SELECT text2
FROM dual
MODEL DIMENSION BY (1 AS x)
MEASURES ('Teste de sttring com quebra de linha a cada 45 caracteres, onde não se deve quebrar a linha no meio de uma palavra. Esta deve ser a mensagem que será quebrada e na cláusula MEASURES variavel tamanho é onde se deve alterar pro tamanho máximo desejado de cada linha...' as text,
0 AS i1, 1 AS i2, CAST(NULL AS VARCHAR2(4000)) AS text2, 45 AS tamanho)
RULES ITERATE (500) UNTIL (i1[1]+tamanho[1] >= LENGTH(text[1]))
( i1[1] = i1[1] + i2[1],
i2[1] = INSTR(SUBSTR(text[1], i1[1],tamanho[1]),' ',-1),
text2[1] = NVL2(text2[1],text2[1] || CHR(10),'') || CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1] THEN SUBSTR(text[1], i1[1]) ELSE SUBSTR(text[1], i1[1],i2[1]) END);
TEXT2
--------------------------------------------
Teste de sttring com quebra de linha a cada
45 caracteres, onde não se deve quebrar a
linha no meio de uma palavra. Esta deve ser
a mensagem que será quebrada e na cláusula
MEASURES variavel tamanho é onde se deve
alterar pro tamanho máximo desejado de cada
linha...
- fsitja
- Rank: OraSauro
- Mensagens: 611
- Registrado em: Seg, 19 Jan 2009 4:29 pm
- Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html
OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist
Nossa, muito bom, o Burga se inspirou
Tomando a liberdade de usar sua solução Burga, eu tinha pensado em algo assim:
Porém, seria utilizando uma tabela com vários textos, no estilo:
Fazendo para N linhas na tabela de origem o buraco fica mais embaixo... teria que fazer um Model multidimensional talvez? Ou misturar query hierárquica com a saída do model?
Sexta-feira, hora do rush... vou deixar pra segunda essa brincadeira.


Tomando a liberdade de usar sua solução Burga, eu tinha pensado em algo assim:
SQL> with tab_texto as (
2 select 'Teste de sttring com quebra de linha a cada 45 caracteres, onde não se deve quebrar a linha no meio de uma palavra. Esta deve ser a mensagem que será quebrada e na cláusula MEASURES variavel tamanho é onde se deve alterar pro tamanho máximo desejado de cada linha...' as text from dual)
3 -- fim dados de exemplo
4 SELECT x as num_linha, linha
5 FROM (select text, rownum as x from tab_texto)
6 MODEL DIMENSION BY (x)
7 MEASURES (text,
8 0 AS i1, 1 AS i2, CAST(NULL AS VARCHAR2(4000)) AS text2, 45 AS tamanho, cast(null as varchar2(4000)) as linha)
9 RULES ITERATE (500) UNTIL (i1[1]+tamanho[1] >= LENGTH(text[1]))
10 ( i1[1] = i1[1] + i2[1],
11 i2[1] = INSTR(SUBSTR(text[1], i1[1],tamanho[1]),' ',-1),
12 text2[iteration_number+1] = NVL2(text2[1],text2[1] || CHR(10),'') || CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1]
13 THEN SUBSTR(text[1], i1[1])
14 ELSE SUBSTR(text[1], i1[1],i2[1]) END,
15 linha[iteration_number+1] =CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1]
16 THEN SUBSTR(text[1], i1[1])
17 ELSE SUBSTR(text[1], i1[1],i2[1]) END
18 );
NUM_LINHA LINHA
---------- --------------------------------------------------------------------------------
1 Teste de sttring com quebra de linha a cada
2 45 caracteres, onde não se deve quebrar a
3 linha no meio de uma palavra. Esta deve ser
4 a mensagem que será quebrada e na cláusula
5 MEASURES variavel tamanho é onde se deve
6 alterar pro tamanho máximo desejado de cada
7 linha...
7 rows selected
with tab_texto as (
select 'Teste de sttring com quebra de linha a cada 45 caracteres, onde não se deve quebrar a linha no meio de uma palavra. Esta deve ser a mensagem que será quebrada e na cláusula MEASURES variavel tamanho é onde se deve alterar pro tamanho máximo desejado de cada linha...' as text from dual union all
select 'texto 2 com mais linhas e por aí vai...' from dual)
Sexta-feira, hora do rush... vou deixar pra segunda essa brincadeira.

-
- Rank: DBA Pleno
- Mensagens: 232
- Registrado em: Qui, 26 Nov 2009 1:05 pm
- Localização: SP
Ricardo H. Tajiri
E aí fsitja... Ótima solução também,
Quebrando em linhas "reais" fica mais facil de visualizar o resultado. Uma coisa que eu não me atentei é no caso de já existir uma quebra de linha no meio do texto. Algumas linhas no resultado final seriam afetadas com essa quebra...
Fiquei curioso quanto ao desafio de fazer pra várias linhas da tabela de origem. A solução que encontrei foi particionar por linha, pros textos serem tratados de forma independente. Deu certo!!!
Olha aí o bichão com as correções e particionando por textos:
Resultado:
Mas ainda não tenho certeza se a condição da cláusula UNTIL está correta, falta fazer mais testes...
Se misturar consulta hierárquica com MODEL e der certo deve ficar bizarro o código, não consigo nem imaginar uma forma de fazer assim...
Vou esperar pra ver se alguém aí se dispõe a arriscar...
Quebrando em linhas "reais" fica mais facil de visualizar o resultado. Uma coisa que eu não me atentei é no caso de já existir uma quebra de linha no meio do texto. Algumas linhas no resultado final seriam afetadas com essa quebra...
Fiquei curioso quanto ao desafio de fazer pra várias linhas da tabela de origem. A solução que encontrei foi particionar por linha, pros textos serem tratados de forma independente. Deu certo!!!

Olha aí o bichão com as correções e particionando por textos:
WITH tab_texto AS (
SELECT 'Teste de sttring com quebra de linha a cada 45 caracteres, onde não se deve quebrar a linha no meio de uma palavra.
Esta deve ser a mensagem que será quebrada e na cláusula MEASURES variavel tamanho é onde se deve alterar pro tamanho máximo desejado de cada linha...' AS text FROM dual
UNION ALL
SELECT 'Teste de string 2 com mais de uma linha na tabela origem.
YEAH-YEAH, pegadinha do malandro!!' AS text FROM dual
UNION ALL
SELECT 'Teste de string 3... Será que vai dar certo???' AS text FROM dual
)
SELECT y AS num_texto, x AS num_linha, linha
FROM (SELECT text, ROWNUM AS y FROM tab_texto)
MODEL
PARTITION BY (y)
DIMENSION BY (1 as x)
MEASURES (text, length(text) tamanho2,
0 AS i1, 1 AS i2, CAST(NULL AS VARCHAR2(4000)) AS text2, 45 AS tamanho, CAST(NULL AS VARCHAR2(4000)) as linha)
RULES ITERATE (500) UNTIL (i1[1]+tamanho[1] > tamanho2[1])
( i1[1] = i1[1] + i2[1],
i2[1] = DECODE(INSTR(SUBSTR(text[1], i1[1],tamanho[1]),CHR(10)),0,INSTR(SUBSTR(text[1], i1[1],tamanho[1]),' ',-1),INSTR(SUBSTR(text[1], i1[1],tamanho[1]),CHR(10))),
text2[1] = NVL2(text2[1],text2[1] || CHR(10),'') || CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1]
THEN REPLACE(SUBSTR(text[1], i1[1]),CHR(10))
ELSE REPLACE(SUBSTR(text[1], i1[1],i2[1]),CHR(10)) END,
linha[iteration_number+1] =CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1]
THEN REPLACE(SUBSTR(text[1], i1[1]),CHR(10))
ELSE REPLACE(SUBSTR(text[1], i1[1],i2[1]),CHR(10)) END
)
ORDER BY 1, 2;
NUM_TEXTO NUM_LINHA LINHA
---------------------- ---------------------- ---------------------------------------------
1 1 Teste de sttring com quebra de linha a cada
1 2 45 caracteres, onde não se deve quebrar a
1 3 linha no meio de uma palavra.
1 4 Esta deve ser a mensagem que será quebrada e
1 5 na cláusula MEASURES variavel tamanho é onde
1 6 se deve alterar pro tamanho máximo desejado
1 7 de cada linha...
2 1 Teste de string 2 com mais de uma linha na
2 2 tabela origem.
2 3 YEAH-YEAH, pegadinha do malandro!!
3 1 Teste de string 3... Será que vai dar
3 2 certo???
12 linhas selecionadas
Se misturar consulta hierárquica com MODEL e der certo deve ficar bizarro o código, não consigo nem imaginar uma forma de fazer assim...

Vou esperar pra ver se alguém aí se dispõe a arriscar...

-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
Semana passada, eu havia postado aqui as alterações que fiz no código que apresentei nesse tópico com relação ao problema que eu estava tendo e funcionou..
O maior problema, por incrível que pareça, está sendo quando justamente a posição de quebra de linha é um espaço em branco.
A rotina está quebrando normalmente, mas ela está pegando a última letra da última palavra antes deste espaço, e está quebrando a linha de forma meio desfigurada..
Ex.: Daniel foi[ESPAÇO]a feira, em vez de ficar assim:
Daniel foi
a feira
Está ficando assim:
Daniel foi
i a feira
Alguém tem alguma idéia??
O maior problema, por incrível que pareça, está sendo quando justamente a posição de quebra de linha é um espaço em branco.
A rotina está quebrando normalmente, mas ela está pegando a última letra da última palavra antes deste espaço, e está quebrando a linha de forma meio desfigurada..
Ex.: Daniel foi[ESPAÇO]a feira, em vez de ficar assim:
Daniel foi
a feira
Está ficando assim:
Daniel foi
i a feira
Alguém tem alguma idéia??
-
- Rank: Estagiário Pleno
- Mensagens: 7
- Registrado em: Qui, 18 Nov 2010 10:12 am
- Localização: Rio de Janeiro
O código que eu havia postado, foi esse abaixo:
set serveroutput on
declare
vTeste Varchar2(1000);
vSaida varchar2(1000);
vPosChar number(10);
vLoopCtrl number(10);
vLoop number(10);
vLastSpace number(10);
vPosNova number(10); -- NOVO
begin
vTeste := 'Daniel Simoes foi ao mercado comprar coisas';
vPosChar := 1;
vLoopCtrl := 1;
vLoop := length(vTeste);
vLastSpace := 0;
vPosNova := 0; -- NOVO
-- Varre toda a linha
while (vLoopCtrl <= vLoop) loop
-- Armazerna a posição do último espaço
if substr(vTeste,vPosChar,1) = ' ' then
vLastSpace := vPosChar;
end if;
-- Verifica se pode fazer a quebra de linha
if (vPosChar = 10) and (vPosChar < vLoop) then
-- Testa para ver se o próximo caractere
-- faz parte da palavra
if substr(vTeste,vPosChar+1,1) <> ' ' then
-- Copia todo o conteudo até a última palavra válida
vSaida := substr(vSaida,1,vLastSpace);
dbms_output.put_line('Trecho Quebra: ' || vSaida);
vPosNova := vLastSpace; -- NOVO
-- Copia o trecho restante
vTeste := Substr(vTeste,vPosNova,Length(vTeste));
vSaida := '';
vPosChar := 1;
vLastSpace := 0;
vPosNova := 0; -- NOVO
vLoopCtrl := 0; -- NOVO
end if;
end if;
vSaida := vSaida || substr(vTeste,vPosChar,1);
vPosChar := vPosChar + 1;
vLoopCtrl := vLoopCtrl + 1;
end loop;
dbms_output.put_line('Trecho Final: ' || vSaida);
end;
-
- Rank: DBA Pleno
- Mensagens: 232
- Registrado em: Qui, 26 Nov 2009 1:05 pm
- Localização: SP
Ricardo H. Tajiri
Se você precisa disso dentro de um bloco em PL/SQL, pode utilizar as consultas que já apresentamos aqui:
set serveroutput on
BEGIN
FOR i IN (
WITH tab_texto AS (
SELECT 'Teste de sttring com quebra de linha a cada 45 caracteres, onde não se deve quebrar a linha no meio de uma palavra. Esta deve ser a mensagem que será quebrada e na cláusula MEASURES variavel tamanho é onde se deve alterar pro tamanho máximo desejado de cada linha...' AS text FROM dual
)
SELECT y AS num_texto, x AS num_linha, linha
FROM (SELECT text, ROWNUM AS y FROM tab_texto)
MODEL
PARTITION BY (y)
DIMENSION BY (1 as x)
MEASURES (text, length(text) tamanho2,
0 AS i1, 1 AS i2, CAST(NULL AS VARCHAR2(4000)) AS text2, 45 AS tamanho, CAST(NULL AS VARCHAR2(4000)) as linha)
RULES ITERATE (500) UNTIL (i1[1]+tamanho[1] > tamanho2[1])
( i1[1] = i1[1] + i2[1],
i2[1] = DECODE(INSTR(SUBSTR(text[1], i1[1],tamanho[1]),CHR(10)),0,INSTR(SUBSTR(text[1], i1[1],tamanho[1]),' ',-1),INSTR(SUBSTR(text[1], i1[1],tamanho[1]),CHR(10))),
text2[1] = NVL2(text2[1],text2[1] || CHR(10),'') || CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1]
THEN REPLACE(SUBSTR(text[1], i1[1]),CHR(10))
ELSE REPLACE(SUBSTR(text[1], i1[1],i2[1]),CHR(10)) END,
linha[iteration_number+1] =CASE WHEN LENGTH(SUBSTR(text[1], i1[1])) <= tamanho[1]
THEN REPLACE(SUBSTR(text[1], i1[1]),CHR(10))
ELSE REPLACE(SUBSTR(text[1], i1[1],i2[1]),CHR(10)) END
)
ORDER BY 1, 2)
LOOP
DBMS_OUTPUT.PUT_LINE(LPAD(i.num_linha,4,'0') || ': ' || i.linha);
END LOOP;
END;
-
- Informação
-
Quem está online
Usuários navegando neste fórum: Nenhum usuário registrado e 4 visitantes