PDA

Ver la Versión Completa : float a decimal: overflow error


sinalocarlos
31-10-2006, 02:15:57
Buen dia

estoy aqui molestandolos de nueva cuanta con un problema que me trae de cabeza

resulta que tengo alrededor de 400 campos FLOAT en mi BD necesito cambiarlos a DECIMAL(18,8) pero el sql se niega a hacerlo argumentando:Código SQL [-] (http://www.clubdelphi.com/foros/#)Arithmetic overflow error converting float to data type numeric

Cabe decir que ya lo he intentado por todas las maneras que mi pobre intelecto lo a permitido:

1.- conversion directa:
set CAMPODECIMAL = CAMPOFLOAT
2.- Con cast y/o convert
3.- creando otra columna DECIMAL despues pasarle los datos
4.- redondeando la columda FLOAT
5.- multiplicando la columna FLOAT por 10000000 redondeandola a 0 digitos y despues pasarla al campo DECIMAL dividiendola entre 10000000
6.- usando un DTS

y otros artilugios

apelo a ustedes a ver si tienen algun truco debajo de la manga para este caso


Carlos
por cierto disculpa por mi Horrortografia

Ricardosml
31-10-2006, 17:49:13
Hola

Probe con algunos valores y solo da problemas si el float tiene mas d diez digitos.
Ese es el caso? tenes algunos valores que superen los 10 digitos?

Si es asi, solo se me ocurre pasarlos perdiendo digitos, cosa q no creo q sea aceptable

Saludos

sinalocarlos
31-10-2006, 18:09:51
Buen dia Ricardosml

En efecto, el error ocurre al intentar pasar datos con mas digitos que los declarados para el nuevo campo, en mi caso (18,8), y sobre la perdida de precicion que mencionas, la causa de el cambio es la poca exactitud que brindan los campos FLOAT, por lo tanto es preferible, en mi caso, sacrificar digitos en esta actualizacion a fin de ganar presicion en los calculos de ahora en adelante.

sobre la sugerencia, lo intente dando un ROUND(campo,8) pero sigue dandome el mismo error, mirando los Books Online encontre que ROUND regresa el mismo tipo de dato que el valor que le mandas, asumo pues que me esta regresando un float con la misma precision que el que le estoy mandando y por lo tanto provoca el overflow (es solo una supocicion), entonces la pregunta seria como truncar a 8 decimales (sin importar la perdida de exactitud) sin utulizar el ROUND, o utilizandolo de forma correcta si el caso es que me estoy equivocando en mi supocicion

Agradecere cualquier comentario

Carlos

Ricardosml
31-10-2006, 18:34:48
creo q no m explique bien, cuando m referia a la cantidad d digitos no me referia a los decimales, sino a la parte entera, creo q el problema se presenta si tenes un numero que tenga mas d 10 digitos.

Saludos

sinalocarlos
31-10-2006, 18:53:17
En efecto Master el problema eran los digitos a la derecha estaba estableciendo un limite de 18 y nunca se me ocurrio revisar que no tuviera cantidades mas grandes que esas, el problema ya quedo les paso el script por si alguien tiene el problema lo pueda solucionar, es recomendable mejorarle pero por cuestiones de tiempo lo deje asi:

declare @s1 varchar(1000), @s2 varchar(1000), @s3 varchar(1000), @s4 varchar(1000), @s5 varchar(1000), @s6 varchar(1000), @s7 varchar(1000), @s8 varchar(1000)
set numeric_roundabort OFF
set nocount ON
declare cur cursor for
select 'ALTER TABLE '+sysobjects.name+' ADD t'+syscolumns.name+' decimal (38,8) NULL ' s1,
'EXEC sp_bindefault ''[dbo].[Cero]'', '''+sysobjects.name+'.t'+syscolumns.name+''' ' s2,
'update '+sysobjects.name+' set t'+syscolumns.name+' = CONVERT (decimal(38,8 ), ROUND('+syscolumns.name+',8)) ' s3,
'update '+sysobjects.name+' set t'+syscolumns.name+' = 0 where t'+syscolumns.name+' is NULL' s4,
'ALTER TABLE '+sysobjects.name+' ALTER COLUMN t'+syscolumns.name+' decimal (38,8) NOT NULL ' s5,
' EXEC sp_unbindefault '''+sysobjects.name+'.'+syscolumns.name+''' ' s6,
'ALTER TABLE '+sysobjects.name+' drop COLUMN '+syscolumns.name+' ' s7,
'EXEC sp_rename '''+sysobjects.name+'.t'+syscolumns.name+''', '''+syscolumns.name+''', ''COLUMN''' s8
from syscolumns inner join sysobjects
on sysobjects.id=syscolumns.id and (sysobjects.xtype='u')
where syscolumns.xusertype = 62
open cur
fetch next from cur into @s1, @s2, @s3, @s4, @s5, @s6, @s7, @s8
while @@fetch_status = 0
begin
exec (@s1)
exec (@s2)
exec (@s3)
exec (@s4)
exec (@s5)
exec (@s6)
exec (@s7)
exec (@s8)
fetch next from cur into @s1, @s2, @s3, @s4, @s5, @s6, @s7, @s8
end
close cur
deallocate cur
set nocount OFF
set numeric_roundabort ON


muchas gracias de nuevo

y espero darme vueltas por aqui mas seguido para contribuir con algo

GRACIAS