IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bases de données Delphi Discussion :

RAD XE - ADO - ACCESS - LONGTEXT


Sujet :

Bases de données Delphi

  1. #1
    Membre du Club
    Profil pro
    Delphi 10.4
    Inscrit en
    Août 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Delphi 10.4

    Informations forums :
    Inscription : Août 2007
    Messages : 51
    Points : 41
    Points
    41
    Par défaut RAD XE - ADO - ACCESS - LONGTEXT
    Bonjour,

    Mon application tente d'être "Multi DB" à partir des composant ADO (ADOQuery et ADOCommand uniquement).

    Après avoir développé pour MySql (Via ADO > ODBC), je tente de rendre mon application compatible Access (JET 4.0). La DB est entièrement gérée par l'application (CREATE TABLE, ALTER, ...) j'ai patiemment converti mes scripts de création MySQL vers ACCESS et notamment une table "Users"

    Deux types de champ me posent problème :

    En MySQL : converti en Acceess par :

    TEXT ...........> LONGTEXT
    LONGBLOG ...........> LONGBINARY

    est-ce correct ?

    Concernant les champs TEXT :

    l' AJOUT (update) se fait via :

    // RIGHTS est un champ TEXT en MySql ou LONGTEXT en access
    // ID_USERS est la clé primaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ADOQuery                 := TADOQuery.Create( nil )  ;
     ADOQuery.Connection := ADOConnection              ;
     ADOQuery.SQL.Clear                                          ;
     AdoQuery.ParamCheck := False                            ;
     
     AdoQuery.SQL.Add( 'UPDATE USERS SET RIGHTS=? '+
                                'WHERE (ID_USERS='+QuotesInteger(ID)+')' ) ;
     
     P := AdoQuery.Parameters.AddParameter                               ;
     P.Name := 'RIGHTS'                                                  ;
     P.LoadFromStream( Stream, ftMemo )                                  ;
     ADOQuery.Prepared := True ;
     try
      ADOQuery.ExecSQL                               ;
     except
     ....
    et ce de manière identique (générique) en MySql et Access et cela fonctionne, les données sont bien enregistrées dans la table..

    Remarque : en MySql l'ID doit être entouré de Quotes (') par en access dans la clause WHERE


    Par contre pour la relecture :
    // DataSet contient le résultat d'une requète sur la table (SELECT * ...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      Stream  := DataSet.CreateBlobStream( DataSet.FieldByName('RIGHTS'), 
                                                           bmRead ) ;
       Strings := TStringList.Create                ;
       Strings.LoadFromStream( Stream )             ;
    .....
    Et bien SEUL le premier caractère du champ LONGTEXT se retrouve dans le Strings[0]. en mode Access, par contre en MySql cela fonctionne, tout le memo est bien dans le TStrings.

    Si j'utilise :
    DataSet.FieldByName( 'RIGHTS' ).AsString

    j'ai tout le contenu dans 1 string .... mais alors j'ai par vraiment la notion de "Memo' et quid de la taille du string si le memo est "gros" de plus mon idée d'objet générique SQL se voit déjà entaché de test selon le serveur utilisé.

    Any Idea

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut


    Tu devais aussi pouvoir écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     AdoQuery.SQL.Add( 
       'UPDATE USERS SET RIGHTS = :paramRIGHTS WHERE ID_USERS = :paramID') ;
     AdoQuery.ParamCheck := true;
      AdoQuery.Parameters.ParamByName('paramRIGHTS').LoadFromStream( Stream, ftMemo )
     AdoQuery.Parameters.ParamByName('paramID').AsInteger := ID;
    ...
    Citation Envoyé par steph1969 Voir le message
    Remarque : en MySql l'ID doit être entouré de Quotes (') par en access dans la clause WHERE
    Etrange, je n'ai jamais fait cela en 5 ans de MySQL !
    Si ton champ est bien un AutoInc et Primary Key, cela supporte un nombre sans quote !

    J'ai plus travaillé sur les BLOB, justement pour éviter tout changement de CharSet, je l'ai fait comme toi avec des Stream mais aussi via la syntaxe MySQL comme :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO MaTable (MonChamp) VALUES (0xFFFFFF...);

    As-tu pensé à l'encodage Unicode ?

    MySQL doit être en UTF8 ou Latin1, je suppose donc le TEXT est converti dans la Base en UTF8 ou Latin1 depuis l'Unicode envoyé comme Stream !

    Qui s'occupe de récupérer la chaine UTF8 et de la convertir en Chaine Unicode !
    J'ignore si c'est Delphi (la couche ADO) ou si c'est le Driver de DB qui le fait (en l'occurence l'objet RecordSet)

    Le fait que tu n'as qu'un seul caractère ferait penser à un zéro (octet de poids fort Unicode) considéré à tord comme une fin de chaine Ansi


    Citation Envoyé par steph1969 Voir le message
    mon idée d'objet générique SQL se voit déjà entaché de test selon le serveur utilisé.
    As-tu déjà touché au Date ? ça aussi c'est SGBG dépendant, ou alors les noms de champs avec caractères spéciaux, les caractères d'échappement, les mots clés ...

    Prévois un système où tu peux facilement gérer chaque DB par un objet générique, par défaut c'est celui-ci qui est utilisé
    à la connexion tu détecte le type, pour chaque type tu associe une classe hérité de l'objet générique, si pas de classe, c'est ce dernier, si classe c'est celle-ci qui est utilisé
    Regarde les patterns Class Registry (équivalent au RegisterClass\FindClass de Delphi), Factory, Strategy ... tu pourras ainsi conserver un code élégant pour le générique et profiter du polymorphisme pour introduire des comportements spécifiques !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre du Club
    Profil pro
    Delphi 10.4
    Inscrit en
    Août 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Delphi 10.4

    Informations forums :
    Inscription : Août 2007
    Messages : 51
    Points : 41
    Points
    41
    Par défaut
    Bonjour et merci pour ta réponse,

    j'avais effectivement essayé avec les paramètres gérés comme tu l'indique et inspiré de la FAQ Delphi .
    Mais bizarement après la ligne
    AdoQuery.ParamCheck := true;
    j'avais pas de paramètres dans AdoQuery.Parameters (count=0). Mainstenant le ADOQuery. Mais je pense pas que cela soit différent ... de plus avec MySql c'est 100% OK (TEXT, LONGBLOB), en écriture / lecture.

    Avec une DB Access, l'écriture semble fonctionner (via un editeur je vois le contenu dans la DB)., c'est juste la récupération via le Stream qui ne fonctionne pas alors qu'avec MySql bien .

    Je vais vérifier avec un LONGBLOB dans un programme test ....

  4. #4
    Membre du Club
    Profil pro
    Delphi 10.4
    Inscrit en
    Août 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Delphi 10.4

    Informations forums :
    Inscription : Août 2007
    Messages : 51
    Points : 41
    Points
    41
    Par défaut
    Bon,

    les champs LONGBLOB (Access et MySql) fonctionnent très bien avec le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      Stream  := DataSet.CreateBlobStream( 'FIELDBLOB', bmRead ) ;
      Stream.ReadBuffer( Buf[0], size ) ;
      Stream.Free ;
    les champs TEXT MySql fonctionnent avec le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        Stream := DataSet.CreateBlobStream( 'FIELDTEXT', bmRead ) ;
        Strings.LoadFromStream( Stream );
        Stream.Free                              ;

    par contre les champ TEXT access ne fonctionne pas avec ce code, mais celui-ci fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        Strings.Text := DataSet.FieldByName('FIELDTEXT').AsString
    la fonction AsString() d'un TField est-elle capable de "renvoyer" un memo (TEXT) de longeur conséquente (disons 200 lignes de 50 caractères) ?

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    200 lignes de 50 caractères, c'est plus qu'un VARCHAR(4000) qui est une limite fréquente des les SGBG comme Oracle ou SQL Server, donc attention c'est le Driver ODDB qui risque de limiter !
    MySQL5.1 lui doit même géré du VARCHAR(65535),
    4000 ou 8000 selon Ansi ou Unicode évidemment !

    On peut espérer que l'ODBC supporte au moins 65535 car en SQL Server, le VARCHAR(MAX) c'est 2Go !

    Un String en Delphi c'est 2Go théorique, donc 1 milliards de caractères Unicode !

    Regarde le Stream, écrit le dans un fichier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      Stream  := DataSet.CreateBlobStream( 'FIELDBLOB', bmRead ) ;
      Stream.ReadBuffer( Buf[0], size ) ;
      Stream.Seek(0, soBeginning);
      Stream.SaveToFile('C:\temp\fichier.hex');
      Stream.Seek(0, soBeginning);
      Stream.Free ;
    Utilise un Editeur Hexa comme UltraEdit !
    Est-ce que le contenu est de la forme :
    • 42 6F 6E 6A 6F 75 72
    • 42 00 6F 00 6E 00 6A 00 6F 00 75 00 72 00


    d'ailleurs Buf c'est quel type ? TBytes ? TByteDynArray ? AnsiString ? String ?

    Tente ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Strings.LoadFromStream( Stream, TEncoding.ASCII);
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre du Club
    Profil pro
    Delphi 10.4
    Inscrit en
    Août 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Delphi 10.4

    Informations forums :
    Inscription : Août 2007
    Messages : 51
    Points : 41
    Points
    41
    Par défaut
    Ok je pense qu'en effet le problème vient du 'tranfert' entre le TStrings et le TStream. je vais essayer cela demain.

    Merci encore

  7. #7
    Membre du Club
    Profil pro
    Delphi 10.4
    Inscrit en
    Août 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Delphi 10.4

    Informations forums :
    Inscription : Août 2007
    Messages : 51
    Points : 41
    Points
    41
    Par défaut
    Voici ce que je viens d'essayer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Stream     := DataSet.CreateBlobStream( 'RIGHTS', bmRead ) ;
    FileStream := TFileStream.Create( 'C:\temp\fichier.hex', fmCreate ) ;
    try
     Stream.Seek(0, soBeginning);
     FileStream.CopyFrom( Stream, Stream.Size )             ;
    finally
     FileStream.Free ;
    end;
    RIGHTS est un champ TEXT dans une DB Access (accéder via ADO "JET 4.0")
    Le contenu du fichier Binaire est composé seumement de 1 byte :

    5B [

    alors que Stream.size = 62 et que le champ (via editeur Mdb) contient :

    [Main]
    .....
    .....

    Bon je garde la solution du FiledByName().AsString qui fonctionne ....
    Par contre la solution via CreateBlobStream fonctionne bien avec des champs LONGBLOB sur des données binaires (fichier PDF stocké dans la DB).

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    Quel est on éditeur Hexa ?
    Si tu fais Clic-Droit Propriété sur le Fichier depuis l'Explorateur de Fichier, quelle taille du fichier ?

    Le Type BLOB n'est pas soumis au gestion de CharSet qui doivent se manifester dans ton cas !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre du Club
    Profil pro
    Delphi 10.4
    Inscrit en
    Août 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Delphi 10.4

    Informations forums :
    Inscription : Août 2007
    Messages : 51
    Points : 41
    Points
    41
    Par défaut
    voice les contenus binaires : (via PSPad Editor Hex)

    En MySql : 29 bytes :
    5B4D 6169 6E5D .... correspondant au texte ascii sur [Main ......

    en msAccess : 62 bytes :
    5B00 4D00 4100 4900 4E00 5D00 ... y'a bien donc une différence de "codage"

    Donc ensuite j'ai essayé :

    En MySql :

    Strings.LoadFromStream( Stream ) ;

    En Ms Access :

    Strings.LoadFromStream( Stream, TEncoding.Unicode ) ;


    Et cela fonctionne alors ...

    Conclusion,

    en MySql le DataSet.CreateBlobStream(...) retourne les données du champ TEXT en Ascii

    en msAccess le DataSet.CreateBlobStream(...) retourne les données du champ LONGTEXT en Unicode ....

    Je sais pas si l'on peut paramétrer cela (se serait peut-être mieux que tout soit en UNICODE pour l'internationnalisation du logiciel)..

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. pbs ado-access
    Par darkzen dans le forum Bases de données
    Réponses: 15
    Dernier message: 01/01/2005, 14h23
  2. [ADO/Access] Appel d’une requête avec des paramètres
    Par Taxenna dans le forum Bases de données
    Réponses: 1
    Dernier message: 07/12/2004, 14h58
  3. [ADO-Access] ADOQuery1.Open (SELECT) -> Erreur non spécif
    Par david_chardonnet dans le forum Bases de données
    Réponses: 3
    Dernier message: 10/11/2004, 15h29
  4. [ADO][ACCESS] Recupération du message d'erreur
    Par samlerouge dans le forum Bases de données
    Réponses: 4
    Dernier message: 24/06/2004, 23h55
  5. [VB6] [ADO] [Access] Changer le mot de passe
    Par dlpxlid dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 03/03/2003, 09h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo