2010-11-23 3 views
7

J'essaie de charger un fichier où toutes les lignes utilisent les mêmes règles. (En supposant HEADER est une seule ligne)MySQL: comment charger des données avec un format de ligne fixe dans des variables utilisateur

HEADER1 
HEADER2 
....... 

Mais malheureusement lorsque je tente d'utiliser l'instruction LOAD DATA INFILE Je reçois cette erreur: Code d'erreur: 1409 Impossible de charger la valeur de fichier avec une taille fixe lignes à la variable.

Voici le code que j'ai écrit:

USE test; 
DROP TABLE IF EXISTS EXAMPLE_H; 
CREATE TABLE EXAMPLE_H(
    ID CHAR(20), 
    SP CHAR(3), 
    IVA CHAR(11) PRIMARY KEY, 
    NLP CHAR(6), 
    DLP DATE, 
    DUVI DATE, 
    DELP CHAR(30), 
    FILLER CHAR(39), 
    VTLP CHAR(3), 
    FILL CHAR(49) 
); 

LOAD DATA INFILE 'BTILSP.TXT' 
    INTO TABLE test.EXAMPLE_H 
    FIELDS TERMINATED BY '' 
    LINES TERMINATED BY '\n' 
    (ID, SP, IVA, NLP, @var_date_one, @var_date_two, DELP, FILLER, VTLP, FILL) 
    SET DLP = str_to_date(@var_date_one, '%Y%m%d', 
     DUVI = str_to_date(@var_date_two, '%Y%m%d'); 

J'ai eu cette idée de lire le fond de this page (commentaire par Ramam Pullella), et j'ai trouvé le même expliqué sur certains sites, mais je ne peux pas comprendre pourquoi je reçois cette erreur. Si je n'utilise pas les variables @var_date_one et @var_date_two, et donc la fonction STR_TO_DATE, la date n'est pas rendue comme MySql a besoin - la date dans le fichier est quelque chose comme "20100701" - alors ce champ serait contenir tous les zéros ou une date différente de ce que j'attends. Si je change DLP et DUVI pour être représenté par CHAR (8), alors cela fonctionne, mais je n'utiliserai pas les comparaisons SQL DATE et les outils similaires.

Pouvez-vous m'aider s'il vous plaît? :) Merci beaucoup.

EDIT:

Il semble que le problème est donnée par la ligne TERMINATED BY « », étant donné que ce genre de ligne est une « ligne fixe (non délimité) ». Peut-être qu'il ne peut pas être assigné à une variable pour une raison inconnue, mais c'est ainsi que cela fonctionne. La documentation dit:

User variables cannot be used when loading data with fixed-row format because user variables do not have a display width.

Toute suggestion?

RE-EDIT: J'ai lu le commentaire de Ryan Neve au bas de cette page. Il donne une astuce pour lire une ligne fixe en variables:

LOAD DATA LOCAL INFILE '<file name>' INTO TABLE <table> 
(@var1) 
SET Date=str_to_date(SUBSTR(@var1,3,10),'%m/%d/%Y'), 
Time=SUBSTR(@var1,14,8), 
WindVelocity=SUBSTR(@var1,26,5), 
WindDirection=SUBSTR(@var1,33,3), 
WindCompass=SUBSTR(@var1,38,3), 
WindNorth=SUBSTR(@var1,43,6), 
WindEast=SUBSTR(@var1,51,6), 
WindSamples=SUBSTR(@var1,61,4); 

Pensez-vous que c'est une bonne façon de le faire? :)

+2

Dans docs mentionné cela ne fonctionnera pas pour les données de format fixe de longueur. Le mieux est de re-réparer votre fichier d'insertion. Ou changez-le en varchar, et effectuez un casting de type plus tard. – ajreal

+0

@ajreal: merci! Hier, je n'ai pas lu votre réponse, mais j'ai édité ma question et j'ai écrit quelque chose comme ce que vous avez dit :) – Markon

Répondre

3

Je ne suis pas un expert, mais il me semble que si les champs sont terminés par une chaîne vide, alors ils doivent être fixés à la place; il doit y avoir un moyen de déterminer les limites entre les champs, et s'il n'y a pas de terminateur, alors ils doivent avoir une taille fixe.

Je remarque que le dit manuel MySQL 5.5:

  • User variables cannot be used when loading data with fixed-row format because user variables do not have a display width.

Il a également (plutôt plus tôt sur la page) dit:

  • If the FIELDS TERMINATED BY and FIELDS ENCLOSED BY values are both empty (''), a fixed-row (nondelimited) format is used. With fixed-row format, no delimiters are used between fields (but you can still have a line terminator). Instead, column values are read and written using a field width wide enough to hold all values in the field. For TINYINT, SMALLINT, MEDIUMINT, INT, and BIGINT, the field widths are 4, 6, 8, 11, and 20, respectively, no matter what the declared display width is.

Étant donné que votre déclaration n'a pas 'FIELDS ENCLOSED BY' et vide ' 'FIELDS ENCLOSED BY', c'est pourquoi vous avez un format fixe. Et donc vous ne pouvez pas faire ce que vous voulez. Parfois, il est plus facile de masser les données en dehors du SGBD - la fixation de la représentation des données pourrait être une de ces opérations.J'ai un programme que j'appelle DBLDFMT que je n'ai pas utilisé depuis quelques années maintenant, mais il peut faire une variété d'opérations, comme convertir des nombres décimaux avec des points décimaux implicites (une astuce mainframe, le champ de prix pourrait être 0023199, représentant la valeur £ 231.99). Il peut aussi gérer les manipulations de date (pas nécessairement en utilisant une notation particulièrement conviviale, mais il est capable de gérer les problèmes que j'ai rencontrés pour obtenir des données de mainframes dans un SGBD Unix - pas MySQL, il n'existait pas quand j'écrivais . Code Contactez-moi si cela pourrait être tout intérêt - voir mon profil

+0

Merci beaucoup pour votre réponse. Cependant, j'ai résolu ce problème comme vous pouvez le lire en bas. – Markon

+1

@Markon: OK - alors peut-être que vous devriez écrire votre réponse comme réponse, et l'accepter après le délai requis (3 jours, mais je ne sais pas si c'est à cause de la question ou de la soumission de votre réponse répondre). Cela permettra d'obtenir la clôture de la question - il ne s'affichera pas comme sans réponse ou sans réponse acceptée/mise à jour. –

+0

Je n'aime pas trop l'idée de répondre à mes questions: P BTW, je ne peux pas voir ce requis dans la FAQ. Si c'est la "procédure", ok, alors la prochaine fois je vais me répondre: P Merci encore :) – Markon

1

Dans le cas où quelqu'un d'autre vient à travers cette Si vous exécutez simplement

LOAD DATA LOCAL INFILE '<file name>' INTO TABLE <table> (@var1) SET ...

sans spécifier FIELDS TERMINATED BY, et votre fichier contient.. Les virgules MySQL se partageront par défaut sur celles-ci:

Dans ce cas, vous pouvez simplement dire à MySQL que votre délimiteur de champ est quelque chose de stupide. par exemple:

FIELDS TERMINATED BY '@@@@@@@@@@@@'

De cette façon, la ligne entière se mettre dans la première « colonne », à savoir votre variable d'utilisateur. Vous pouvez ensuite l'utiliser exactement comme indiqué dans votre code en haut.

Il convient de noter traite MySQL delimiter une chaîne, donc vous pouvez même avoir
FIELDS TERMINATED BY 'this_string_thoes_not_appear_in_my_file si vous voulez

+0

Merci pour le partage! – Markon

Questions connexes