Mostrando entradas con la etiqueta Desarrollo. Mostrar todas las entradas
Mostrando entradas con la etiqueta Desarrollo. Mostrar todas las entradas

29 octubre 2017

DBA WARS: "It's an older code sir, but it checks out."


En esta entrada del blog vamos a dar salida a varios còdigos SQL Y PL/SQL, antiguos pero todavía válidos.

Problemas con de PL / SQL Developer de Allround Automations

Al usar este IDE e su versión 11.X, una consulta interna toma muchos ciclos de CPU en el servidor de la base de datos (100% de una CPU).
¿Es este tu problema?  Por favor, compruebe si hay una consulta al lanzar el editor con el siguiente formato de consulta:
select s.synonym_name object_name, o.object_type
from sys.all_synonyms s, sys.all_objects o where s.owner in ('PUBLIC', user) and o.owner = s.table_owner and o.object_name = s.table_name and o.object_type in ('TABLE', 'VIEW', 'PACKAGE','TYPE', 'PROCEDURE', 'FUNCTION', 'SEQUENCE');
Se debe a la opción Describir contexto del asistente de código. Para deshabilitar:
Mira en: Tools> Preferences> Code Assistant y deshabilitar la opción "Describe Context".
O comprarles la versión 12.X que ya está resuelto.


Depurar papelera de reciclaje anterior a ...


Tiene la papelera de reciclaje de la base de datos llena o su tamaño es considerablemente grande, pero no quiere hacer un "Borrado" completo?
¿Quieres eliminar solo más de x días (como más de 90 días)?

Una buena forma de hacerlo es:

# 90 días
Select 'purge table '||owner||'."'||OBJECT_NAME||'";' from dba_recyclebin where type='TABLE' and to_date(droptime,'YYYY-MM-DD:HH24:MI:SS')<sysdate-90;
# 90 minutos
Select 'purge table '||owner||'."'||OBJECT_NAME||'";' from dba_recyclebin where type='TABLE' and to_date(droptime,'YYYY-MM-DD:HH24:MI:SS')<sysdate-(90/(24*60));

Mirar esta nota de Metalink (Doc ID 1596147.1) por si teneis alguna qe otra duda.


Purga mejorada de la papelera de reciclaje Oracle

Desde que en la versión 10g de la base de datos , se introdujo el 'reciclaje' para segmentos. Si se establece el parámetro recyelebin = on, y se descarta una tabla, en realidad no se descarta; se renombra a un nombre generado por el sistema. Esto realmente puede ayudar en situaciones donde una tabla se cae accidentalmente, ya que se puede recuperar fácilmente. Sin embargo, sin monitorearlo, puede terminar causando problemas de muchos tipos, porque puede terminar hinchando el número total de segmentos en la base de datos a muchas veces más de lo que era antes.
Oracle solo tiene 4 métodos publicados para descartar lotes de objetos reciclados; siendo:

  • El comando SQL> PURGE RECYCLE BIN emitido por un propietario de segmento, que purga todos los segmentos reciclados para ese usuario.,
  • El comando SQL> PURGE DBA_RECYCLEBIN, emitido por un DBA, que purga todos los objetos reciclados en la base de dato.
  • El comando SQL> PURGE TABLESPACE <tablespace_name> USER <schema_name>; que purga objetos propiedad del propietario dado.
  • El comando SQL> PURGE TABLESPACE uwdata USUARIO uwclass; que purga los objetos propiedad del propietario y el espacio de tabla dados.
No hay comandos incorporados que permitan que solo los segmentos de papeleras de reciclaje se realicen antes de cierto tiempo, o que solo reciclen objetos de la papelera con más de un cierto número de versiones recicladas de la misma tabla. Es relativamente fácil crear un procedimiento almacenado para manejar estos casos; esto explica cómo se puede hacer eso.

En PL/SQL, tenemos:


create or replace procedure purge_user_recyclebin(
  p_purge_before_date   in date default=NULL,
  p_purge_keep_versions in number default=NULL,
  p_test_only           in varchar2 := 'Y'
)
is
  cursor c_purge_before_date is
    select object_name
    from  user_recyclebin
    where droptime > p_purge_before_time
    and   can_purge = 'YES'
    order by droptime;

  cursor c_purge_before_version is
     select * from 
       (select original_name,
               type,
               object_name,
               droptime,
               rank() over (partition by original_name,type order by droptime desc) as obj_rank
         from   user_recyclebin
         where  can_purge = 'YES')
       where obj_rank > p_purge_keep_versions
       order by droptime;

  v_sql varchar2(1024);

  exception e_bad_parameters;
  exception e_38302;
  pragma exception_init(e_38302,-38302);  

  procedure runsql(p_object_name in varchar2) 
  is
  begin
    v_sql := 'purge '||p_object_name;
    if (p_test_only = 'N') then
      begin
        execute immediate v_sql;
      exception
         when e_38302 then 
           dbms_output.put_line('Cuidado, el objeto '||p_object_name||' no existe ignóralo');
         when others then
           dbms_output.put_line('Error borrando '||p_object_name);
           dbms_output.put_line(dbms_utility.format_error_backtrace);
      end;
    else
      dbms_output.put_line(v_sql);
    end if;
  end;

begin

  if p_purge_before_date is not null and
     p_purge_keep_versions is null then
     for r in c_purge_before_date loop
       runsql(r.object_name);
     end loop;
  elsif p_purge_before_date is null and
     p_purge_keep_versions is not null then
     for r in c_purge_before_version loop
       runsql(r.object_name);
     end loop;
  else
     raise e_bad_parameters;
  end if;

end purge_user_recylebin;
/

Cómo usarlo

Si desea probar para ver qué haría, sin purgar nada, simplemente pase el parámetro 'p_test' al valor 'Y', y establezca la salida del servidor en el tamaño 1000000. Esto mostrará una lista de los comandos que se ejecutarían. pero en realidad no los ejecuta.

Purgar todos los objetos de la papelera de reciclaje antes de una fecha determinada
Esto purgará todos los objetos de reciclaje reciclados antes del 1 de noviembre, a medianoche.

execute purge_user_recylebin(to_date('20150801 00:00:00','YYYYMMDD HH24:MI:SS'),NULL,'Y');

Esto, cuando se ejecuta como propietario de un esquema, ayuda a mantener la cantidad de objetos reciclados a un nivel razonable, a la vez que se conserva, la capacidad de recuperar segmentos perdidos más recientemente.




15 noviembre 2016

PL / SQL: Evitar algoritmos innecesariamente complejos



Si tienes un equipo de  programadores nuevos en PL / SQL (y SQL), no es raro encontrar que complican demasiado las cosas, escribiendo más código de lo necesario y poniendo demasiada lógica en PL / SQL. Ese problema puede ser agravado por accidentalmente obtener la "respuesta correcta" basada en pruebas inadecuadas y datos de prueba.

Supongamos que tengo una tabla y un conjunto de datos como sigue:



# 1. Éxito accidental con datos de prueba incorrectos


CREATE TABLE undead_type
(
   undead_id     INTEGER PRIMARY KEY,
   undead_name   VARCHAR2 (100)
)
/

BEGIN
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (1, 'Skeleton');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (2, 'Zombie');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (3, 'Ghoul');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (4, 'Wight');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (5, 'Wraith');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (6, 'Mohrg');
  INSERT INTO undead_type (undead_id, undead_name)
        VALUES (7, 'Ghast');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (8, 'Mummy');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (9, 'Lich');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (10, 'Demilich');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (11, 'Vampire Spawn');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (12, 'Vampire');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (13, 'Allip');
   COMMIT;
END;
/
Y tengo que escribir un programa que produce la siguiente salida: 
Undead en Orden Alfabético: 
  • Allip 
  • Demilich 
  • Ghast
  • ...
DECLARE
   l_count   INTEGER;
   l_name    plch_animals.animal_name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('Animals in Alphabetical Order');

   SELECT COUNT (*) INTO l_count FROM plch_animals;

   FOR indx IN 1 .. l_count
   LOOP
      SELECT animal_name
        INTO l_name
        FROM plch_animals
       WHERE animal_id = indx;

      DBMS_OUTPUT.put_line (l_name);
   END LOOP;
END;
/

# 2. Demasiado SQL, datos insuficientes

DECLARE
   TYPE undead_ids_t IS TABLE OF undead_type.undead_id%TYPE;

   l_undead_ids   undead_ids_t;
   l_name         undead_type.undead_name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('undead in Alphabetical Order');

   SELECT undead_id
     BULK COLLECT INTO l_undead_ids
     FROM undead_type;

   FOR indx IN 1 .. l_undead_ids.COUNT
   LOOP
      SELECT undead_name
        INTO l_name
        FROM undead_type
       WHERE undead_id = indx;

      DBMS_OUTPUT.put_line (l_name);
   END LOOP;
END;
/

# 3. Vamos a pasarlo bien con las conexiones PL/SQL con colecciones

DECLARE
   TYPE undead_ids_t IS TABLE OF undead_type.undead_id%TYPE
      INDEX BY undead_type.undead_name%TYPE;

   l_undead_ids   undead_ids_t;
   l_index        undead_type.undead_name%TYPE;
   l_name         undead_type.undead_name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('undeads in Alphabetical Order');

   FOR rec IN (  SELECT *
                   FROM undead_type
               ORDER BY undead_name DESC)
   LOOP
      l_undead_ids (rec.undead_name) := rec.undead_id;
   END LOOP;

   l_index := l_undead_ids.FIRST;

   WHILE l_index IS NOT NULL
   LOOP
      DBMS_OUTPUT.put_line (l_index);

      l_index := l_undead_ids.NEXT (l_index);
   END LOOP;
END;
/

#4. SQL Simple

SELECT undead_name FROM undead_type
 ORDER BY undead_name;

No es mucho más simple que eso. Y si lo necesita dentro de PL / SQL

 #5. PL/SQL Simple

 BEGIN
   DBMS_OUTPUT.put_line ('undead in Alphabetical Order');

   FOR rec IN (SELECT undead_name FROM undead_type
                ORDER BY undead_name)
   LOOP
      DBMS_OUTPUT.put_line (rec.undead_name);
   END LOOP;
END;


Lecciones aprendidas 


  •  Deje a SQL hacer el levantamiento de pesas, tanto como sea posible (no es que haya algo muy "pesado" para levantar en este ejercicio!) 
  • No sobre-complicar las cosas. Asegúrese de que sus datos de prueba tengan suficiente volumen y variedad para ejercer realmente su algoritmo. 
  • Si te encuentras pensando "¿tiene que ser tan complicado?", Casi con toda seguridad la respuesta es un resonante "No!" Y debe dar un paso atrás, desafiar sus suposiciones, y ver cómo se puede simplificar su código

04 noviembre 2016

¿Y tú de quien eres?: SQL para mostrar consultas jerárquicas en Oracle



En algunas ocasiones, es necesario recuperar los datos de una tabla cuya relación es recursiva, para mostrar pertenencias y/o jerarquías (por ejemplo litados de reportes de organizaciones, desglosadas por departamentos, direcciones, etc). Tales jerarquías generalmente son representadas a través de estructuras tipo árbol, en donde la raíz (o nodo principal) tiene ramas (nodos descendientes) y cada una de estas ramas puede a su vez generar más ramas, hasta llegar a un punto final en donde no hay mas divisiones. Esos nodos terminales son pues llamados también hojas.



Para el ejemplo, supongamos que se tiene una tabla donde se tiene almacenados los datos familiares de personas en una tabla como la siguiente:

idPersona
Nombres
hijoDe
1
Juan Carlos

2
Luis
5
3
Pedro
5
4
Jaime Alberto
9
5
Olga María
1
6
Marta Edith
8
7
Lucía
9
8
Nelly
1
9
Felipe
8
10
Edgar Nelson
8

La anterior tabla, almacena los datos acerca de los padres de cada persona. De esta manera, es posible construir un árbol como el siguiente:


Desde la versión 9i, el lenguaje sql de oracle provee la posibilidad de recuperar los datos de una tabla, vista, o tabla externa, simulando el recorrido de un árbol, el cual puede hacerse comenzando por la raía hasta llegar a todas las hojas, o desde las hojas hasta llegar a la raíz.

Por lo tanto, La consulta:

SELECT nombres, LEVEL
FROM persona
START WITH nombres='Juan Carlos'
CONNECT BY PRIOR idPersona = hijode;

Retornará el nombre de todas las personas y el id del respectivo padre; empezando por el nombre Juan Carlos. La Pseudocoluma LEVEL indica el nivel en el que se encuentra el registro, tras haber construido el arbol. START WITH indica el registro raiz; es decir, donde empieza el arbol. CONNECT BY PRIOR indica las columnas en las cuales existe la relación padre-hijo

Salida:


Si desea recuperar la descendencia a partir de “Felipe”, la consulta sería:



Obsérvese que en la anterior consulta el valor de LEVEL para “Felipe” es igual a 1, ya en el árbol que construye esta consulta, el nodo “Felipe” se encuentra en el primer nivel.

Si por el contrario, se desean conocer los padres de Felipe, la consulta sería:




Obsérvese en el anterior ejemplo, que el recorrido se hizo de abajo hacia arriba (en el árbol). El orden de las columnas en la clausula CONNECT BY PRIOR, especifica el orden del recorrido. En el primer ejemplo se tenía:CONNECT BY PRIOR idPersona=hijoDe y se tuvo el recorrido del árbol de arriba a abajo. En el ultimo ejemplo se tuvo CONNECT BY PRIOR hijoDe =idPersona, y el recorrido fue de abajo hacia arriba.

De igual manera, desde la versión 9i, fue incluida la función SYS_CONNECT_BY_PATH(), que concatena los valores de las ramas del árbol en el recorrido.

El siguiente es un ejemplo de su utilización:




Es muy fácil entonces hacer consultas jerárquicas con la utilización de la cláusula STARA WITH y CONNECT BY y la función SYS_CONNECT_BY_PATH.

NBA y COALESCE


La función COALESCE recibe varios argumentos y retorna la primer expresión distinta de nulo de la lista de dichos argumentos.


  • Sintaxis


COALESCE ( expression [ ,...n ] )


  • Argumentos


expression: Puede ser una expresión de cualquier tipo.


  • Tipos de valor devueltos

Devuelve el tipo de datos de expression con la precedencia de tipo de datos más alta.
Nota: Si todos los argumentos son NULL, COALESCE devuelve NULL.
Al menos uno de los valores NULL debe ser NULL con tipo.

COALESCE(expression1,...n) es equivalente a esta función CASE:

CASE
WHEN (expression1 IS NOT NULL) THEN expression1
...
WHEN (expressionN IS NOT NULL) THEN expressionN
ELSE NULL
END

ISNULL y COALESCE, aunque son equivalentes, pueden comportarse de forma diferente.
Una expresión que contenga ISNULL con parámetros diferentes de NULL se considera que es NOT NULL, mientras que las expresiones que contienen COALESCE con parámetros que son diferentes de NULL se consideran NULL.

En este ejemplo, la tabla NBA_TEAM_TICKETS_SOLDS incluye tres columnas con información acerca del precio de entradas vendidas por cada equipo de la NBA.
Para determinar el importe total por cada equipo, utilice la función COALESCE para obtener sólo los valores no NULL encontrados en hourly_wage, price y commission.



CREATE TABLE NBA_TEAM_TICKETS_SOLDS

(

party_day_wage number NULL,

price number NULL,

commission number NULL,

num_sales int NULL 

);

/

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(10.00, NULL, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(20.00, NULL, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(30.00, NULL, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(40.00, NULL, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, 10000.00, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, 20000.00, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, 30000.00, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, 40000.00, NULL, NULL);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, NULL, 15000, 3);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, NULL, 25000, 2);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, NULL, 20000, 6);

INSERT NBA_TEAM_TICKETS_SOLDS VALUES(NULL, NULL, 14000, 4);

/

SELECT CAST(COALESCE(party_day_wage * 40 * 52, price, commission * num_sales) AS money) AS 'Total sales' FROM NBA_TEAM_TICKETS_SOLDS;
/

Total Sales

------------

20800.0000

41600.0000

62400.0000

83200.0000

10000.0000

20000.0000

30000.0000

40000.0000

45000.0000

50000.0000

120000.0000


18 enero 2015

Oracle 12cR1 novedades (Parte II); Columnas Identidad



Oracle 12c Nueva característica – Columnas Identidad

Viendo las nuevas características de la versión 12c, encontré que ahora podemos definir una columna con el  tipo de dato Identity, tal como lo tiene desde hace tiempo IBM DB2, en concreto desde la versión 8.0, de la siguiente manera:

SQL>CREATE TABLE table (col1 INT,col2 DOUBLE,col3 INT NOT NULL GENERATED ALWAYS AS IDENTITY;
(START WITH 100, INCREMENT BY 5))

Que significa una columna Identity?
Es incorporar a una columna la propiedad de ser auto numérica.


COLUMN_NAME  GENERATED [ ALWAYS | BY DEFAULT [ ON NULL ] ]AS                                  
  IDENTITY  [ ( identity_options ) ]

Donde

  • ALWAYS      Indica que no será necesario introducir un valor para esta columna en una sentencia insert. Por el contrario indicar un valor aunque sea Null, da un error ORA-32795.
  • BY DEFAULT  Le permite utilizar Identity, si la columna no se hace  referencia en la una sentencia insert, pero si se hace referencia a la columna, el valor especificado se utiliza en lugar de la  identidad. El intento de especificar el valor NULL en este caso se traduce en un error, ya que las columnas de identidad son siempre NOT NULL. 
  • BY DEFAULT [ON NULL]: Si en una sentencia INSERT se mete un valor NULL, esta se generará un nuevo valor, si en cambio si mete un valor para esta columna, se insertará el valor de la sentencia.
Contras al implementar esta característica
  1. Dado a que una columna definida como IDENTITY está vinculada a una secuencia, le ocurre lo mismo que si la secuencia se define por fuera, por lo cual si una sentencia INSERT abortara, los números de la secuencia se perderían.
  2. En el caso de hacer una copia de seguridad de una tabla, se exportaría con todos sus valores, la querer importar esa tabla. 
  • Solución: Deberíamos tener en cuenta que la columna IDENTITY  este en by default porque en caso contrario daría error.
Conclusión 
La inclusión de las columnas IDENTITY, es un importante avance, ya que encapsula en una sentencia INSERT la obtención del nextval de la secuencia. Como ocurre con IBM DB2 o M$ SQL Server.

Por otro lado la inclusión de las opciones By Default y By Default On Null, permiten que los valores puedan ser internos o externos. Lo más importante es que esto lo hacemos casi sin que perdamos performance.

Mi opinion
Esta es una característica poco aseada que se ha introducido unos 20 años tarde. En mi opinión, que fácilmente podría haber sido implementado en Oracle 6.0. Podría ser útil para nuevas aplicaciones, aunque la cantidad de tiempo y esfuerzo ahorrado es insignificante. Para las aplicaciones existentes de la relevancia de esta nueva característica es más cuestionable;´Nadir va a mezclar estilos de codificación y modificar código funcional, por una característica que apenas aporta nada.

Oracle 12cR1 novedades (Parte I); Columnas Invisibles



Oracle 12cR1 – Columnas Invisibles


La primera de las Nuevas Características de Oracle 12c que vamos a traer a este blog son las columnas invisibles. Es una de las opciones menos controvertidas y mas sencillas de explicar.

La idea básica de las columnas básicas es que ellos permiten ser ocultadas desde las aplicaciones.  Las columnas se pueden hacer invisibles en la sentencia CREATE TABLE o posteriormente utilizando una sentencia ALTER TABLE. Por defecto columnas son visibles. Columnas invisibles pueden hacerse visibles de nuevo utilizando una sentencia ALTER TABLE.

¿Como funciona todo esto?

El siguiente ejemplo crea una tabla con una columna invisible:
SQL> CREATE TABLE ejemplo1
(
  c1 NUMBER,
  c2 NUMBER INVISIBLE,
  c3 NUMBER,
  c4 NUMBER
);

SQL> DESC ejemplo1
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------
 C1                                                 NUMBER
 C3                                                 NUMBER
 C4                                                 NUMBER

SQL*Plus puede opcionalmente mostrar columnas implementando la opción COLINVISIBLE.
SQL> SET COLINVISIBLE ON

SQL> DESC ejemplo1
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------
 C1                                                 NUMBER
 C3                                                 NUMBER
 C4                                                 NUMBER
 C2 (INVISIBLE)                                     NUMBER

A pesar de que la columna es invisible, en esa columna todavía se pueden visualizar y modificar. Por ejemplo:

SQL> INSERT INTO ejemplo1 (c1,c2,c3,c4) VALUES (11,12,13,14);

1 row created.
SQL> SELECT c1,c2,c3,c4 FROM ejemplo1;

        C1         C2         C3         C4
---------- ---------- ---------- ----------
        11         12         13         14

Mirad, que en el ejemplo superior, todas las columnas son listadas tanto en las sentencias INSERT y SELECT. Que ocurre si omitimos los nombres de las columnas en la sentencia INSERT?

INSERT INTO ejemplo1 VALUES (21,22,23,24)
            *
ERROR at line 1:
ORA-00913: too many values

La sentencia INSERT falla por que estamos intentando meter ina columna invisible en la columna (C2). Si nosotros lo intentamos otra vez omitiendo para C2 la sentencia INSERT será correcta:


SQL> INSERT INTO ejemplo1 VALUES (21,22,24);

1 row created.

SQL> SELECT c1,c2,c3,c4 FROM ejemplo1;

        C1         C2         C3         C4
---------- ---------- ---------- ----------
        11         12         13         14
        21                    22         24

Observa que el valor para C2 es NULL para cada fila encontrada. SELECT * no devuelve las columnas invisibles. Por ejemplo:

SQL> SELECT * FROM ejemplo1;

        C1         C3         C4
---------- ---------- ----------
        11         12         14
        21         22         24

Una columna invisible puede ser visible de nuevo, por ejemplo:
ALTER TABLE ejemplo1 MODIFY c2 VISIBLE;

Una columna visible puede ser invisible, por ejemplo:

ALTER TABLE ejemplo1 MODIFY c2 INVISIBLE;

15 octubre 2012

Superar la limitación de los N caracteres con el paquete DBMS_OUTPUT.PUT_LINE


 Si hablamos de versiones de de Oracle Database anteriores a 10g R2 
Oracle facilitó el paquete DBMS_OUTPUT para los desarrolladores de PL/SQL. La función PUT_LINE() es la característica más utilizada por los desarrolladores Oracle. PUT_LINE se usa para mostrar resultados en la pantalla o para mostrar resultados en el spool y sacarlo a un archivo. Pero esta función tiene un límite solo permite 255 caracteres y si te pasas se provoca una excepción PL/SQL.
declare
   v_str varchar2(1000); 
begin 
   for i in 1..275 
   loop 
      v_str := v_str || TO_CHAR(i); 
   end loop; 
   dbms_output.put_line( v_str);
end;
/
Si ejecutamos el código en un motor de base de datos anterior a Oracle 10g R2, nos devuelve el error: 

ORA-20000: ORU-10028: line length overflow, limit of 255 chars per line.

Para solventar este problema podremos crear un procedimiento almacenado que sobrescriba el comportamiento de esta función de tal manera que divida la información en paquetes de 255 caracteres y la una en la salida.

create or replace procedure rafa.custom_output(in_string in varchar2 )
is 
   out_string_in long default in_string; 
   str_len number; 
   loop_count number default 0; 
begin 
   str_len := length(out_string_in);
   while loop_count < str_len
   loop 
      dbms_output.put_line( substr( out_string_in, loop_count +1, 255 ) ); 
      loop_count := loop_count +255; 
   end loop; 
end;

Si ejecutamos este código en nuestro motor de versión anterior a Oracle 10g R2, no dará el error.

declare
   v_str varchar2(1000); 
begin 
   for i in 1..275 
   loop 
      v_str := v_str || TO_CHAR(i); 
   end loop; 
   rafa.custom_output( v_str);
end; 
/
Si hablamos de versiones de de Oracle Database posteriores a 10g R2 Oracle amplió el tamaño de los caracteres a 32,767 bytes (el mismo límite superior que tiene otro paquete UTL_FILE). Este código ya no da ningún error para versiones del motor 10g R2 y 11g.

set linesize 64
BEGIN
DBMS_OUTPUT.PUT_LINE( RPAD('x',255,'x') );
END;
/

Si ejecutamos este código en un motor Oracle 10g R2 o superior, dará el siguiente error:

BEGIN
DBMS_OUTPUT.PUT_LINE( RPAD('$',32767,'$') || 'incluso mas...' );
END;
/
BEGIN
*
ERROR at line 1:
ORA-20000: ORU-10028: line length overflow, limit of 32767
bytes per line
ORA-06512: at "SYS.DBMS_OUTPUT", line 32
ORA-06512: at "SYS.DBMS_OUTPUT", line 91
ORA-06512: at "SYS.DBMS_OUTPUT", line 112
ORA-06512: at line 2

SQL> set serveroutput on size unlimited 
SQL> show serveroutput
serveroutput ON SIZE UNLIMITED FORMAT WORD_WRAPPED
Para ver que la opción ilimitada funciona, intentaremos sacar una salida superior al límite del buffer para esta opción (1000000 bytes). El siguiente ejemplo mostrará 1048544 bytes.

SQL> set lines 100
 
SQL> BEGIN
  2     FOR i IN 1 .. ((1000000/32767)+1) LOOP
  3        DBMS_OUTPUT.PUT_LINE( RPAD('$',32767,'$') );
  4     END LOOP;
  5  END;
  6  /
 
PL/SQL procedure successfully completed.
Eso si si abusamos de este código saldrá este error entre otro, así que cuidado con los experimentos, amiguitos: 
ORA-04030: out of process memory when trying to allocate 4120 bytes.