Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » PostgreSQL »

Problema con datos reales

Estas en el tema de Problema con datos reales en el foro de PostgreSQL en Foros del Web. Hola a todos tengo un problema cuando inserto registros a una tabla, detallo: create table detalle( codigo character(2), importe1 real not null, importe2 real not ...
  #1 (permalink)  
Antiguo 15/07/2009, 09:47
 
Fecha de Ingreso: septiembre-2008
Mensajes: 75
Antigüedad: 15 años, 7 meses
Puntos: 1
Problema con datos reales

Hola a todos tengo un problema cuando inserto registros a una tabla, detallo:

create table detalle(
codigo character(2),
importe1 real not null,
importe2 real not null
);

1. en una funcion envio los registros a grabar en mi tabla detalle
insert into detalle(codigo,importe1,importe2) values('10',13930,0.0);

insert into detalle(codigo,importe1,importe2) values('20',2646.7,0.0);

insert into detalle(codigo,importe1,importe2) values('30',165.77,0.0);

insert into detalle(codigo,importe1,importe2) values('40',0.0,16742.47);


2. luego antes de terminar la funcion comparo que la sumas de importe1 e importe2 sean iguales sino aborto la funcion; y hago q me salga el mensaje que la sumas no coinciden, pero aparentemente deberia de no salir el error pero me sale

agradeceria me ayudaran en que estoy fallando

gracias
  #2 (permalink)  
Antiguo 15/07/2009, 10:01
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problema con datos reales

Que error te sale?
Cual es la función?
Como comparas las sumas?
Entre mas detalles ofrezcas, mas facil será para alguien ayudarte.

Un saludo edwinsp
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #3 (permalink)  
Antiguo 15/07/2009, 10:31
 
Fecha de Ingreso: septiembre-2008
Mensajes: 75
Antigüedad: 15 años, 7 meses
Puntos: 1
Respuesta: Problema con datos reales

Gracias por la atencion.

1. la funcion es la siguiente:

CREATE OR REPLACE FUNCTION pa_grabardetalle(_codigo character[], _aimporte real[])
RETURNS integer AS
$BODY$
BEGIN
FOR i IN array_lower(_aimporte,1) .. array_upper(_aimporte,1) LOOP
nitem:=nitem+1;
insert into public."Detalle"(codigo,importe1,importe2)
VALUES(_codigo[i],_aimporte[i][1],_aimporte[i][2]);
END LOOP;
if (select sum(importe1)-sum(importe2) from public."Detalle" Where codigo=_codigo)<>0 then
RAISE EXCEPTION 'las sumas no coinciden..!';
RETURN 0;
end if;
RETURN 1;
END;

2. en si no es error del servidor de datos, el error es el que especifico cuando las sumas no coinciden luego de verificarla asi en la funcion
if (select sum(importe1)-sum(importe2) from public."Detalle" Where codigo=_codigo)<>0 then
RAISE EXCEPTION 'las sumas no coinciden..!';
RETURN 0;
end if;

Lo curioso es que venia grabando normalmente hasta que corri la funcion con estos datos

Select "pa_grabardetalle"(ARRAY['10','20','30','40'],ARRAY[[13930.00,0.0],[2646.7,0.0],[165.77,0.0],[0.0,16742.47]]) as resultado;

gracias nuevamente
  #4 (permalink)  
Antiguo 15/07/2009, 10:49
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problema con datos reales

No te entiendo muy bien.
Cita:
if (select sum(importe1)-sum(importe2) from public."Detalle" Where codigo=_codigo)<>0 then
el campo código de que tipo es?
estas comparando un campo código con un vector?

Con que datos te funciona correctamente?
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #5 (permalink)  
Antiguo 15/07/2009, 11:15
 
Fecha de Ingreso: septiembre-2008
Mensajes: 75
Antigüedad: 15 años, 7 meses
Puntos: 1
Respuesta: Problema con datos reales

Vamos desde el principio he tenido errores al explicar

--Tabla
create table detalle(
codcab character(2) not null,
codigo character(2) not null,
importe1 real not null,
importe2 real not null
);

--Funcion
CREATE OR REPLACE FUNCTION pa_grabardetalle(_codcab character,_codigo character[], _aimporte real[])
RETURNS integer AS
$BODY$
BEGIN
FOR i IN array_lower(_aimporte,1) .. array_upper(_aimporte,1) LOOP
nitem:=nitem+1;
insert into detalle(codcab,codigo,importe1,importe2)
VALUES(_codcab,_codigo[i],_aimporte[i][1],_aimporte[i][2]);
END LOOP;
if (select sum(importe1)-sum(importe2) from detalle Where codcab=_codcab)<>0 then
RAISE EXCEPTION 'las sumas no coinciden..!';
RETURN 0;
end if;
RETURN 1;
END;

--Ejecucion que no corre
Select "pa_grabardetalle"('10',ARRAY['10','20','30','40'],ARRAY[[13930.00,0.0],[2646.7,0.0],[165.77,0.0],[0.0,16742.47]]) as resultado;

----Ejecucion que corre
Select "pa_grabardetalle"('20',ARRAY['10','20','40'],ARRAY[[100.00,0.0],[19,0.0],[0.0,119]]) as resultado;

Espero ser ahora preciso disculpa por los errores anteriores
  #6 (permalink)  
Antiguo 15/07/2009, 13:12
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problema con datos reales

Edwinsp

Mira lo que he probado.

Código sql:
Ver original
  1. -- Function: pa_grabardetalle(_codcab bpchar, _codigo bpchar[], _aimporte real[])
  2.  
  3. -- DROP FUNCTION pa_grabardetalle(_codcab bpchar, _codigo bpchar[], _aimporte real[]);
  4.  
  5. CREATE OR REPLACE FUNCTION pa_grabardetalle(_codcab bpchar, _codigo bpchar[], _aimporte REAL[])
  6.   RETURNS REAL AS
  7. $BODY$
  8. BEGIN
  9. FOR i IN array_lower(_aimporte,1) .. array_upper(_aimporte,1) LOOP
  10. INSERT INTO detalle(codcab,codigo,importe1,importe2)
  11. VALUES(_codcab,_codigo[i],_aimporte[i][1],_aimporte[i][2]);
  12. END LOOP;
  13. IF (SELECT SUM(importe1)-SUM(importe2) FROM detalle WHERE codcab=_codcab)<>0 THEN
  14. --RAISE EXCEPTION 'las sumas no coinciden..!';
  15. RETURN (SELECT SUM(importe1)-SUM(importe2) FROM detalle WHERE codcab=_codcab)::REAL;
  16. END IF;
  17. RETURN 1;
  18. END;
  19. $BODY$
  20.   LANGUAGE 'plpgsql' VOLATILE;

Esto me retorna el valor que deberia ser 0. Para mi sorpresa el valor el valor retornado es muy cercano a 0.
Lo extraño realmente, es que si te fijas en la tabla detalle, las inserciones se hacen correctamente.

Sigo buscando la razón de este fenomeno.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #7 (permalink)  
Antiguo 15/07/2009, 13:27
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problema con datos reales

Función un poco mas estable.

Código sql:
Ver original
  1. CREATE OR REPLACE FUNCTION pa_grabardetalle(_codcab bpchar, _codigo bpchar[], _aimporte NUMERIC[][])
  2.   RETURNS FLOAT AS
  3. $BODY$
  4. BEGIN
  5. FOR i IN array_lower(_aimporte,1) .. array_upper(_aimporte,1) LOOP
  6. INSERT INTO detalle(codcab,codigo,importe1,importe2)
  7. VALUES(_codcab,_codigo[i],round(_aimporte[i][1]::NUMERIC,2),round(_aimporte[i][2]::NUMERIC,2));
  8. END LOOP;
  9. IF (SELECT round((SUM(importe1)-SUM(importe2))::NUMERIC,2) FROM detalle WHERE codcab=_codcab)::NUMERIC <> 0::NUMERIC THEN
  10. --RAISE EXCEPTION 'las sumas no coinciden..!';
  11. RETURN (SELECT SUM(importe1)-SUM(importe2) FROM detalle WHERE codcab=_codcab)::NUMERIC;
  12. END IF;
  13. RETURN 1;
  14. END;
  15. $BODY$
  16.   LANGUAGE 'plpgsql' VOLATILE;

Sigo buscando. Todavía no me lo explico.



EDITO: OTRA MAS ESTABLE AUN, PERO FALLA DESPUES DE 10 INSERCIONES.
FALLA EN EL RETORNO DE LA FUNCIÓN, PERO TODAS LAS INSERCIONES SE HACEN CORRECTAMENTE


Código SQL:
Ver original
  1. CREATE OR REPLACE FUNCTION pa_grabardetalle(_codcab bpchar, _codigo bpchar[], _aimporte NUMERIC[][])
  2.   RETURNS NUMERIC AS
  3. $BODY$
  4. DECLARE
  5. suma_1 record;
  6. suma_2 record;
  7. diferencia NUMERIC;
  8. BEGIN
  9. FOR i IN array_lower(_aimporte,1) .. array_upper(_aimporte,1) LOOP
  10. INSERT INTO detalle(codcab,codigo,importe1,importe2)
  11. VALUES(_codcab,_codigo[i],_aimporte[i][1],_aimporte[i][2]);
  12. END LOOP;
  13. SELECT INTO suma_1 SUM(importe1) AS suma1 FROM detalle WHERE codcab=_codcab;
  14. SELECT INTO suma_2 SUM(importe2) AS suma2 FROM detalle WHERE codcab=_codcab;
  15. diferencia := round(suma_1.suma1::NUMERIC,2)-round(suma_2.suma2::NUMERIC,2);
  16. IF (diferencia <> 0.00) THEN
  17. --RAISE EXCEPTION 'las sumas no coinciden..!';
  18. RETURN diferencia;
  19. END IF;
  20. RETURN 99;
  21. END;
  22. $BODY$
  23.   LANGUAGE 'plpgsql' VOLATILE;

Estoy ofendido... Por que razón toma los valores con decimales escondidos?
Sigo buscando
__________________
Without data, You are another person with an opinion.
W. Edwads Deming

Última edición por huesos52; 15/07/2009 a las 13:44
  #8 (permalink)  
Antiguo 15/07/2009, 14:49
 
Fecha de Ingreso: septiembre-2008
Mensajes: 75
Antigüedad: 15 años, 7 meses
Puntos: 1
Respuesta: Problema con datos reales

no tendra que ver en algo el tipo de dato en este caso real, mira hice esto

ejeccucion con error:
Select "pa_grabardetalle"('10',ARRAY['10','20','30','40'],ARRAY[[13930.00,0.0],[2646.7,0.0],[165.77,0.0],[0.0,16742.47]]) as resultado;

ejecucion corrio normal
Select "pa_grabardetalle"('10',ARRAY['10','20','30','40'],ARRAY[[13930.00,0.0],[2646.7,0.0],[165.767,0.0],[0.0,16742.467]]) as resultado;

mira alli te daras cuenta que grabe registros con 3 decimales y no me salio el mensaje de las sumas no coinciden

pero cuando vi los registros grabados, el registro que deberia estar asi:
codcab|codigo|importe1|importe2
10 |40 |0.0 |16742.467

estaba asi:
codcab|codigo|importe1|importe2
10 |40 |0.0 |16742.5

no me refleja la precision, que pasara ? alguna explicacion
  #9 (permalink)  
Antiguo 16/07/2009, 08:09
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: Problema con datos reales

Encontré una solución y una explicación.
La explicación está aca, donde afirman los posibles problemas de exactitud de cierto tipo de datos. Para datos exactos, se recomienda usar el tipo de dato numeric con scale.

La solución:

Código sql:
Ver original
  1. CREATE TABLE detalle(
  2. codcab CHARACTER(2) NOT NULL,
  3. codigo CHARACTER(2) NOT NULL,
  4. importe1 NUMERIC(8,2) NOT NULL,
  5. importe2 NUMERIC(8,2) NOT NULL
  6. );
  7.  
  8. --Funcion
  9. CREATE OR REPLACE FUNCTION pa_grabardetalle(_codcab CHARACTER,_codigo CHARACTER[], _aimporte NUMERIC[][])
  10. RETURNS NUMERIC AS
  11. $BODY$
  12. BEGIN
  13. FOR i IN array_lower(_aimporte,1) .. array_upper(_aimporte,1) LOOP
  14. INSERT INTO detalle(codcab,codigo,importe1,importe2)
  15. VALUES(_codcab,_codigo[i],round(_aimporte[i][1]::NUMERIC,2),round(_aimporte[i][2]::NUMERIC,2));
  16. END LOOP;
  17. IF (SELECT SUM(importe1)-SUM(importe2) FROM detalle WHERE codcab=_codcab)<>0 THEN
  18. RAISE EXCEPTION 'las sumas no coinciden..!';
  19. RETURN 0;
  20. END IF;
  21. RETURN 1;
  22. END;
  23. $BODY$
  24. LANGUAGE 'plpgsql' VOLATILE;

Si deseas mas decimales de exactitud, cambia la escala en la declaración de la tabla y el casteo en el insert dentro del trigger.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #10 (permalink)  
Antiguo 16/07/2009, 09:56
 
Fecha de Ingreso: septiembre-2008
Mensajes: 75
Antigüedad: 15 años, 7 meses
Puntos: 1
Respuesta: Problema con datos reales

mil gracias huesos52, me reforzaste la idea del tipo de dato que tambien tenia en mente, nuevamente te agradezco
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:42.