jueves, 31 de marzo de 2011

ORA-01403: no data found,ORA-01403: no data found ,ORA-23494: too many rows and Select Into

ORA-01403: no data found ,ORA-23494: too many rows for destination and Select Into
ORA-01403: no data found
Cause: In a host language program, all records have been fetched. The return code from the fetch was +4, indicating that all records have been returned from the SQL query.

Action: Terminate processing for the SELECT statement.

ORA-23494: too many rows for destination "string"
Causa: The specified destination has too many rows
Acción: Ensure the specified destination has at most two valid rows before retrying this operation.

Esto es lo que encuentras al buscar este error.

no data found, Como olvidar este error, y aqui te presento a uno de los principales culpables:

Select datos
Into variables
from tabla

Dentro de las mas grandes bendiciones/maldiciones que existen en pl/sql esta esta bendita/maldita sentencia, porque se preguntaran?, bueno pues resulta de que cuando te enseñan esta sentencia, debería venir de la mano con un manual de por que deberías evitar utilizarla, a que me refiero:

Cuando tu utilizas la sentencia select into , significa que de manera directa deseamos obtener información de la base y que nos la deposite dentro de variables en nuestro código, que utilizado correctamente nos puede ahorrar algunas lineas de código dentro de nuestros procedimientos, sin embargo si no estas absoluta y completamente seguros de que tu consulta siempre regresara uno y solo un registro, en caso de que no estés seguro de lo anterior, tu proceso debería estar preparado para lo peor.

es decir deberia por lo menos agregar el siguiente codigo:

begin
Select datos
Into variables
from tabla
exceptions
when no_data_found then
/*lo que quieras hacer cuando no encuentre datos*/
when too_many_rows
/*lo que quieras hacer cuando encuentre mas de un registro */
end;



Espero este pequeño ejemplo sea útil.

miércoles, 30 de marzo de 2011

Order by en columnas de tipo caracter

Normalmente cuando nos encontramos con reportes que entregan una columna de numero de documento , el usuario solicitara que la información se le entregue ordenada con respecto a este campo , pero que pasa cuando esta columna incluye datos tanto alfanuméricos?

a pues si se ordenan puede darte cosas como estas


10000000001
111011
1111
A1201


cual es la solución mas sencilla ,

agregar en las seccion del order by


select (datos)
 from tabla
order by lpad(columna,longitud columna,'0')

 Un ejemplo con la tabla de transacciones de la ebs

select trx_number
  from ra_customer_trx_all
order  by  lpad(trx_number,50,'0')

si esta tabla tuviera solo los datos de arriba los presentaría asi

1111
A1201
111011
10000000001

 Espero que les sea útil , felices reportes.

jueves, 3 de marzo de 2011

ALTER SEQUENCE NEXTVAL ?

Algunas veces cuando realice un proceso que servía para generar la generación de un archivo me solicitaron que le colocara un numero como folio al archivo. Y esto fue muy sencillo solo me base en una secuencia de Oracle. Todo funciono muy bien hasta que llego el momento en el que me dijeron "Necesitamos regenerar la secuencia por que lanzamos muchos archivos mal y no podemos gastar esos folios así por que si".





A pues resulta que no hay una manera directa de colocarle el siguiente valor a una secuencia, y esto se puede conseguir de dos maneras (las que conozco):







  • Drop Sequence: Simplemente hacer drop al objecto de base de datos y colocar en la construción del objeto la sentencia "start with " y el numero en el que les soliciten iniciar:


drop sequence my_seq;



create sequence my_seq



start with 1234



nocache



order;



/





  • Manera comoda, buscando por ahí se encontraran con que no existe un comando alter sequence nextval, pero hay una manera de hacerlo por medio de jugar con lo que nos brinda Oracle: ALTER SEQUENCE MINVAL, ALTER SEQUENCE INCREMENT BY.


EL siguiente procedimiento de pl se encarga de realizar el truco mas cómodamente :


CREATE OR REPLACE PROCEDURE XXX_RESET_SEQUENCE (

PS_SEQ_NAME IN VARCHAR2, P_STARTVALUE IN NUMBER) AS

LN_VAL NUMBER (30);

MIN_VAL NUMBER (30);

LS_BUFF VARCHAR2(25);

LS_CYCLE_FLAG VARCHAR2(25);

BEGIN

SELECT CYCLE_FLAG

INTO LS_CYCLE_FLAG FROM USER_SEQUENCES

WHERE SEQUENCE_NAME =PS_SEQ_NAME;

EXECUTE IMMEDIATE 'SELECT ' PS_SEQ_NAME '.NEXTVAL FROM dual'INTO LN_VAL;

LN_VAL := -1*(LN_VAL - P_STARTVALUE 1);

EXECUTE IMMEDIATE 'ALTER SEQUENCE ' PS_SEQ_NAME' MINVALUE 0';

LS_BUFF := ' INCREMENT BY ';

EXECUTE IMMEDIATE 'ALTER SEQUENCE ' PS_SEQ_NAME LS_BUFF LN_VAL;

EXECUTE IMMEDIATE 'SELECT ' PS_SEQ_NAME '.NEXTVAL FROM dual'

INTO LN_VAL;

EXECUTE IMMEDIATE 'ALTER SEQUENCE ' PS_SEQ_NAME ' INCREMENT BY 1';

END XXX_RESET_SEQUENCE;

/

Y de la siguiente manera se cambiaria el valor de la secuencia;

BEGIN

XXX_RESET_SEQUENCE('MY_SEQ',2);

END;

/

Ventajas y Desventajas

Drop:

Ventaja puede iniciar desde 0(cero), es directo.

Desventaja, al hacer drop del objeto se invalidan todas las dependencias de este.

Procedimiento:

Desventaja: No me permitió iniciar en 0(cero) el valor más bajo al que llego es 1.

Ventaja: No requiere recompilación de dependencias.

Espero que les sea útil.