2009-09-24 15 views
1

Nous insérons des valeurs dans une colonne de base de données SQL Server 2005 de type NUMERIC (19,5) à partir de Perl. Tant que les valeurs absolues sont .0001 ou supérieur, cela fonctionne. Cependant, lorsque les valeurs vont à la 5ème décimale, Perl commence à les stocker au format exponentiel (-9e-05 au lieu de -0.00009), puis l'erreur "Error converting data type varchar to numeric" provient de SQL Server. Comment pouvons-nous empêcher cela et le faire insérer correctement de petites valeurs numériques?Pourquoi est-ce que j'obtiens «Erreur lors de la conversion du type de données varchar en numérique» sur un nombre à virgule flottante en Perl?

Nous utilisons v5.8.5 Perl, DBI 1,56, DBD :: Sybase 1,07 et SQL Server 2005.

Le code est à peu près ce qui suit, mais j'ai enlevé les champs étrangers:

$invoice->{IL_UNITPRICE} = 0.09; # Actually comes from another database 
$invoice->{IL_PRICEUNITCONV} = 0.001; # Actually comes from another database 
$unitprice = $invoice->{IL_UNITPRICE} * -1 * $invoice->{IL_PRICEUNITCONV}; 
#$unitprice equals -9e-05 at this point. 
$sth = $dbh->prepare('INSERT INTO foo (bar) VALUES (?)'); 
$sth->execute($unitprice); 

La ligne ci-dessus échoue avec l'erreur: DBD::Sybase::st execute failed: Server message number=8114 severity=16 state=5 line=2 server=baz text=Error converting data type varchar to numeric.

Répondre

2

Essayez

$sth->execute(sprintf("%.6f",$unitprice)); 

Pour développer un bit - Lorsque vous transmettez un float/double natif via l'interface DBi, il est converti en une chaîne qui, si vous ne spécifiez pas le contraire, utilise les conventions de formatage par défaut de Perl (imposées par le compilateur C). La valeur par défaut est la précision à 6 chiffres, et si le nombre a plus que cela, il est rendu en notation scientifique.

Pour obtenir le format à virgule fixe, vous devez le demander explicitement, en utilisant sprintf.

+0

Il semble plutôt incommode de devoir rappeler les nombres à virgule flottante pour forcer le formatage correctement, plutôt que d'avoir le format à virgule flottante automatique de Perl correctement manipulé. – LeBleu

+0

Oui, mais une décision de swith à la notation scientifique doit se produire à un point, et ils ont simplement choisi d'aller avec la valeur par défaut du compilateur. Pour en savoir plus, voir http://perldoc.perl.org/perlnumber.html –

+0

la valeur par défaut de la bibliothèque C, pas celle du compilateur. – ysth

0

En fait, je pense qu'en utilisant Math::Bigint et son Math :: BigFloat associé résoudrait également ce problème. Chaque fois que j'utilise des flottants ou des nombres d'une taille suffisamment grande, j'utilise ces modules, donc je n'ai pas besoin de lancer sprintf partout sauf quand je veux vraiment contrôler le formatage.