2017-05-18 5 views
1

J'utilise actuellement LOAD DATA LOCAL INFILE pour importer des données financières volumineuses pour traitement.Valeurs tronquées DECIMAL dans mysql (30 décimales)

Les valeurs dans le fichier sont stockées avec une précision de 30 décimales, par ex.

125.154821679413246187945612314846

Lorsque cela a importé cependant, les données sont toujours tronquée à 10 décimales près, avec zéros, par exemple

125.154821679200000000000000000000

La colonne est configurée comme suit: -

USDPayable DECIMAL (33,30)

EDIT:

Table script de création:

CREATE TABLE IF NOT EXISTS dump 
         (
          SaleID INT NOT NULL AUTO_INCREMENT, 
          Country VARCHAR(8), 
          Label VARCHAR(20), 
          Product VARCHAR(5), 
          URI VARCHAR(20), 
          UPC VARCHAR(20), 
          EAN VARCHAR(20), 
          ISRC VARCHAR(20), 
          TrackName VARCHAR(28), 
          ArtistName VARCHAR(64), 
          ComposerName VARCHAR(64), 
          AlbumName VARCHAR(54), 
          Quantity INT(10), 
          USDPayable decimal(33,30), 
          PRIMARY KEY (SaleID) 
         ); 

charge script données:

LOAD DATA 
    LOCAL INFILE '<my file>' 
    INTO TABLE dump 
     IGNORE 3 LINES 
       (Country, Label, Product, URI, UPC, EAN, ISRC, 
       TrackName, ArtistName, ComposerName, AlbumName, 
       Quantity, USDPayable) 

échantillon de données d'entrée:

BE Label1 product code 00cflHmwefweidJA barcode ISRC ......... 1 0.003872402660862401479116078884 
US Label2 product code 00cflHmtyfweidJA barcode ISRC ..........1 0.002220695558213356018688393633 
BE Label2 product code 00cflHmwefweidJA barcode ISRC ..........2 0.002137613958913373918420510406 
NO Label3 product code 00cflHmjkfweidJA barcode ISRC ..........3 0.02264616748080050066133527663 
DE Label4 product code 00cflHmwefweidJA barcode ISRC ..........1 0.003018216435957714580945696704 
CO Label5 product code 00cflHmzxfweidJA barcode ISRC ..........1 0.0004178407583000146349569881848 
CA Label6 product code 00cflHmwefpoidJA barcode ISRC ..........2 0.01385864190292964399955986534 
CA Label7 product code 00cflHmwefmnidJA barcode ISRC ..........1 0.003270121556795672746439239972 
IS Label7 product code 00cflHmwefweidJA barcode ISRC ..........8 0.05702767311942350853930831032 
TR Label7 product code 00cf09poefweidJA barcode ISRC ..........4 0.009839895102632677068730014884 

MISE À JOUR

Après un certain temps, j'ai décidé de mordre la balle - et diffusez la ligne par ligne fichier en utilisant PHP prêt à traiter les valeurs avant d'insérer dans la table. en utilisant fgets(), cette valeur est aussi tronquée ici ... C'est presque comme si mysql et php pensaient que les valeurs tronquées sont les valeurs littérales dans le fichier lors de sa lecture. Très confus

+0

try number_format() –

+0

@BilalAhmed Pouvez-vous nous en dire plus? Si vous voulez dire la fonction PHP, j'espérais éviter tout pré-traitement (ce qui explique l'utilisation de LOAD DATA LOCAL INFILE), car le fichier contient plusieurs centaines de milliers de lignes – locksem

+0

S'il vous plaît considérer un [edit] à votre question à afficher nous quelques lignes de votre fichier d'entrée, et la sortie de 'SHOW CREATE TABLE quelquechose 'pour la table que vous essayez de charger. Il semble que MySQL lit les nombres de votre fichier INFILE, les convertit en leur format natif interne - virgule flottante en double précision - puis les convertit en décimal, perdant ainsi de la précision. Vous pouvez essayer de placer ces nombres entre guillemets afin que 'LOAD DATA INFILE' suppose qu'ils sont des chaînes de texte, pas des nombres, sur le chemin. –

Répondre

1

php est une langue faiblement typée. S'il voit quelque chose qu'il suppose être un nombre décimal, il le gère comme float - un nombre approximatif de précision double ieee 754 - par défaut. Il en va de même pour le traitement numérique interne de MySQL.

ieee 754 la précision double n'est pas assez précise pour vos calculs de redevances (dommage les pauvres musiciens, vous ne pouvez rien acheter avec un millionième de centime).

Vous avez donc raison de déclarer un type décimal de haute précision pour votre table. Mais vous devez tromper MySQL dans la manipulation de vos numéros comme s'ils étaient des chaînes, et ne pas prendre son raccourci préféré ieee 754 (ou pirater, on pourrait dire).

Vous pouvez essayer quelque chose comme ceci:

LOAD DATA 
LOCAL INFILE 'C:\\yadda\\yadda\\sample.tsv' 
    INTO TABLE dump 
      (Country, Label, Product, URI, UPC, ISRC, Quantity, @USDPayable) 
     SET USDPayable = CAST(@USDPayable AS DECIMAL(33,30)); 

Cela prendra les dispositions nécessaires pour traiter vos petites fractions de dollars sous forme de chaîne en entrée, puis le convertir au format décimal dont vous avez besoin à l'aide d'une clause SET.

Notez que la liste des colonnes entre parenthèses attribue cette valeur à chaque colonne à @USDPayable.

Cela a fonctionné pour moi. Si cela ne fonctionne pas pour vous, vous devriez probablement envisager de passer à une version ultérieure de MySQL.

Notez que vous devrez modifier la liste des colonnes pour vos données réelles.Vous n'avez pas fourni certaines colonnes dans votre fichier tsv d'exemple.

Soyez prudent avec la saisie de données faible avec ce genre de données monétaires. Veuillez vérifier que vos sommes sont exactes. Vous devrez peut-être passer à une langue fortement typée.

+1

Je suis un gars facile à demander de l'aide par les gens qui paient des redevances aux musiciens. Beaucoup de musiciens parmi ma famille et mes amis. –

+0

Merci beaucoup @ O.Jones cela semble avoir fait l'affaire bien - et beaucoup d'informations utiles supplémentaires. Cela m'a rendu plutôt douteux de continuer à compter sur PHP pour ce genre de chose! – locksem