Creation d'une API sgbd demande conseil.SQL Server

Creation d'une API sgbd demande conseil.SQL Server - SQL/NoSQL - Programmation

Marsh Posté le 05-01-2005 à 21:17:52    

Bonjours.
Actuellement je suis en train de faire une API multi sgbd écrit en PHP (normal si je suis ici).
Je demande conseil à savoir comment je peux pointer sur l'enregistrement afin de modifier le contenu de ce dernier. J'ai regardé plus ou moin ce que fait phpmyadmin. Il se base sur la pagination d'apres ce que j'ai compris. Le probleme c'est qu'au moment ou ont a la liste des enregistrements et au moment ou je vais cliquer dessus un utilisateur peut rajouter un enregistrement entre temps et décaler les informations.
Comment être sur que je vais bien tomber sur le bon enregistrement ?
Merci!
 
EDIT : Trouvé, en faite il est possible de récupérer le rowid sous Mysql en faisant  

Code :
  1. SELECT _rowid FROM ma_table.


 
C'est d'la bombe de balle bb  [:x-oni]  
sous  PostGreSQL c'est "oid" Oracle "rowid"
Acces, Paradox, SqlServer il y a pas :/
 
Merci Arjuna de m'avoir mis sur la voix  :jap:
 


Message édité par Berceker United le 12-02-2005 à 16:37:13
Reply

Marsh Posté le 05-01-2005 à 21:17:52   

Reply

Marsh Posté le 06-01-2005 à 09:43:57    

Base-toi sur le rowid.
 
C'est chiant à récupérer, parceque tous les SGBD n'utilisent pas le même système pour isoler le rowid, mais c'est le seul moyen d'être certain qu'on modifie la ligne sélectionné.
 
Sinon, t'as aussi la solution d'interroger la base afin de récupérer la PK de la table, et filtrer ton update en fonction de la valeur de cette PK. Je sais pas ce que permettent les outils PHP, mais avec MDAC, t'as juste besoin de faire un cnx.OpenShema(...) afin de retrouver les information quant au shéma du SGBD (Bases, Tables, Colonnes de table, Indexes, Vues, Clé étrangères, Clé primaires, etc.), ce qui évite d'aller interroger les tables systèmes qui diffèrent d'un SGBD à l'autre.


Message édité par Arjuna le 06-01-2005 à 09:44:27
Reply

Marsh Posté le 06-01-2005 à 15:42:05    

Arjuna a écrit :

Base-toi sur le rowid.
 
C'est chiant à récupérer, parceque tous les SGBD n'utilisent pas le même système pour isoler le rowid, mais c'est le seul moyen d'être certain qu'on modifie la ligne sélectionné.
 
Sinon, t'as aussi la solution d'interroger la base afin de récupérer la PK de la table, et filtrer ton update en fonction de la valeur de cette PK. Je sais pas ce que permettent les outils PHP, mais avec MDAC, t'as juste besoin de faire un cnx.OpenShema(...) afin de retrouver les information quant au shéma du SGBD (Bases, Tables, Colonnes de table, Indexes, Vues, Clé étrangères, Clé primaires, etc.), ce qui évite d'aller interroger les tables systèmes qui diffèrent d'un SGBD à l'autre.


Merci pour ta réponse.
Concernant le rowid, il y a pas d'equivalent sur "Mysql" mais sera interessant pour les autres sgdb.
En php il y a une commande permettant récupérer des informations sur la table ainsi que la clé primaire mais lorsqu'il y a pas de clé primaire sur une table ça renvoy null c'est donc délicat.
Il y a la solution de jouer sur la page et numéro de ligne afficher et lorsque l'ont sur le lien c'est de récupérer les caracteristique suivant :
numero page
nombre d'enregistrement par page
numero de ligne selectionné
 
Problème si jamais l'utilisateur fait un select avec clause et qu'entre temps il y a un enregistrement qui rentre dans cette clause et qu'il est censé rentré dans la page en cour il peut y avoir un décalage au moment ou il va cliquer.
Bref il y a un risque non négligeable.  
J'ai une solution un peut bencale :/  
Créer un table temporaire du resultat du select et lorsque je fais un select il compare a la table temporaire si le resultat sont différent c'est qu'il y eu un ajout entre temps.

Reply

Marsh Posté le 06-01-2005 à 17:05:53    

Tu m'étonnes grandement quant au rowid. Les SGBD utilisent tous en interne un rowid, sinon ils ne pourraient pas fonctionner.
 
Ensuite, ton histoire du "page 5 ligne 12" (par exemple), je le sent mal.
En effet, outre le fait que tu as de grandes chances qu'une personne change la position de la ligne (en supprimant une ligne avant, ou en en ajoutant une avant), je ne vois surtout pas comment tu vas pouvoir générer une instruction "update" qui va mettre à jour "la ligne 12 à la page 5" (même en faisant un 4 * nblpp + 12 pour retrouver la bonne ligne), y'a pas moyen de mettre ça comme filtre dans un sgbd...

Reply

Marsh Posté le 06-01-2005 à 17:42:54    

Ok je saisi le problème. j'avous que je suis pas chaud pour aller regarde le code source de phpmyadmin pour savoir comment il font :/

Reply

Marsh Posté le 06-01-2005 à 17:48:46    

nan, mais je suis certain que mysql peut te donner un équivalent de rowid (ou alors ils ont vraiment pas assuré sur ce coup là...)
 
mais je suis certain que ça marche, parceque OLEDB permet d'ouvrir des dataset dynamiques sur mysql, et oledb tout comme toi à absolument de bosser sur le rowid pour être certain de mettre à jour la ligne demandée.

Reply

Marsh Posté le 06-01-2005 à 18:36:39    

Je viens de regarder la doc php en détail et il y a rien qui retourne un quelconque identifiant de la ligne en court. J'ai regardé la fonction mysql_data_seek mais bon je crois pas qu'il m'aidera plus.  
J'ai regardé dans la doc Mysql et je ne vois rien qui renvoy un identifiant.  
En fait j'ai créé une table ne possedant pas de clé primaire comme test pour voir le comportement.
Je crois que je vais rester sur l'idée d'utiliser une table temporaire comme référence a mes données.

Reply

Marsh Posté le 06-01-2005 à 19:33:49    

Ouais, mais si dans ta table sans clé tu as :
 
toto
titi
titi
titi
tata
tata
 
Si je veux mettre à jour le second "titi", tu vas faire comment ? Sans connaître la ligne exacte (à l'intérieur du sgbd) tu ne pourras pas trouver.
 
Sinon, sûr et certain, ce ne sera pas dans la doc PHP, ou ce sera une pure coïncidence. C'est plutôt côté mySQL qu'il faut regarder.

Reply

Marsh Posté le 06-01-2005 à 19:43:19    

En effet, je viens de vérifier dans la doc MySQL et il n'y a pas de RowId. C'est carrément hallucinant (même dans la toute dernière version).
 
Je te souhaite un bon courage.
 
Je savais que mySQL n'était pas fiable, mais alors là, ça dépasse l'entendement !

Reply

Marsh Posté le 06-01-2005 à 20:03:10    

Arjuna a écrit :

En effet, je viens de vérifier dans la doc MySQL et il n'y a pas de RowId. C'est carrément hallucinant (même dans la toute dernière version).
 
Je te souhaite un bon courage.
 
Je savais que mySQL n'était pas fiable, mais alors là, ça dépasse l'entendement !


Je le constaste aussi ! :/ c'est assez bizarre qu'il ne renvoy pas cette information. En faite phpmyadmin ne garantie la ligne selectionné.
Comme je l'ai dit je vais utilisé un table temporaire pour m'assuré qu'il y aura pas une erreur et évite de passer 36 000 paramètres.
Merci pour ton aide. Je vais acheter le livre de référence sur le SQL peut être qu'il y a une réponse. J'espere que j'aurais pas de problème avec SqlServer, PostgreSQL, et toute la clik :/
 
Merci encore.


Message édité par Berceker United le 06-01-2005 à 20:06:16
Reply

Marsh Posté le 06-01-2005 à 20:03:10   

Reply

Marsh Posté le 06-01-2005 à 20:13:58    

SqlServer et PostgreSQL, sûr et certain, ont leur propre RowId (même si c'est pas forcément super évident à utiliser avec SQL Server)
 
Sinon, juste un conseil. MDAC (Plateforme Windows uniquement malheureusement) permet d'accéder à la plupart des bases du marché. Et via les outils qu'il contient (recordset) il permet de faire énormément de choses de façon extrêment facile et de façon générique.
 
Entre autre, il a un support implicite des rowid, y compris avec mySQL.
 
A partir de là, je pense que c'est une bonne chose de l'utiliser.
 
Par contre, pour profiter de ces fonctions "online" de MDAC, il te faut une application qui reste "alive" entre deux traîtements. Tu vas donc être obligé à mon sens de laisser tomber le PHP pour passer à un programme style C++/VB/Java ou autre. (attention, avec Java ça risque d'être un peu le binz à utiliser, parcequ'il utilise son propre système de connection aux bases, qui passe par une surcouche de MDAC, je ne sais pas si y'a tout dedans)

Reply

Marsh Posté le 06-01-2005 à 23:11:10    

En faite ça a pas pour but commercial. Je fais cela pour bien assez bien maitriser l'environnement objet et pour reussir à détourner un problème sans laisser une chance à une erreur vu à l'avance comme pour ce problème de la ligne d'enregistrement. Java j'en ai fais et c'est un peut relou :/ mais je compte quand même le réecrire en java=>jsp aussi.
Merci pour tes conseil.
 
PS: D'ailleur j'aurais voulu savoir s'il y a des choses qui manque a phpmyadmin a ceux qui l'utilise.


Message édité par Berceker United le 06-01-2005 à 23:20:37
Reply

Marsh Posté le 06-01-2005 à 23:19:31    

Arjuna a écrit :

(attention, avec Java ça risque d'être un peu le binz à utiliser, parcequ'il utilise son propre système de connection aux bases, qui passe par une surcouche de MDAC, je ne sais pas si y'a tout dedans)


ouh la :o
ca passe par un driver jdbc, et c'est tout. Maintenant, c'est possible que certains drivers utilisent mdac, mais ca m'étonnerais fortement. Déja pour la plupart, c'est du pur java (comprendre : pas de dépendance native). Maintenant peut-etre que des machins windows-only ont ce genre de dépendances, mais je n'y crois pas.
 
tu as une source de ce que tu annonces ?

Reply

Marsh Posté le 07-01-2005 à 00:31:23    

Je parlais pour quand on fait de l'ODBC par exemple. Sur plateforme Windows, JDBC ne fait que se connecter à MDAC, qui est le fournisseur ODBC de Windows.
 
Après, c'est pas nouveau comme info, ça a peut-être changé depuis.

Reply

Marsh Posté le 07-01-2005 à 00:36:34    

Berceker United a écrit :


PS: D'ailleur j'aurais voulu savoir s'il y a des choses qui manque a phpmyadmin a ceux qui l'utilise.


Truc qui manque dans tous les outils d'admin de base, où rarement complet (mise à par quelques exceptions peut-être)
 
1) Générer un document SQL contenant les objets sépectionnés (avec ou sans données). SQL Server le fait, sauf pour les données par exemple.
2) Capacité de gérer plusieurs bases de types différents à la fois (avoir dans une frame une base mySQL et dans une autre une base PostgreSQL par exemple)
3) Pouvoir interragir entre deux bases : dupliquer la structure et les données, comparer structure et données y compris quand ce sont 2 SGBD distincts.


Message édité par Arjuna le 07-01-2005 à 00:37:27
Reply

Marsh Posté le 07-01-2005 à 00:47:54    

Arjuna a écrit :

Truc qui manque dans tous les outils d'admin de base, où rarement complet (mise à par quelques exceptions peut-être)
 
1) Générer un document SQL contenant les objets sépectionnés (avec ou sans données). SQL Server le fait, sauf pour les données par exemple.
2) Capacité de gérer plusieurs bases de types différents à la fois (avoir dans une frame une base mySQL et dans une autre une base PostgreSQL par exemple)
3) Pouvoir interragir entre deux bases : dupliquer la structure et les données, comparer structure et données y compris quand ce sont 2 SGBD distincts.


 
1 - Pas compris peux-tu parler en version light :D  
2 - C'est justement ce que je fais.(Mysql, PostGreSQL, SqlServer, Sqli).
3 - c'est prévus et laisser la possibiliter a l'utilisateur de faire les correpondance entre les différents type de champs des deux base de données différentes.

Reply

Marsh Posté le 07-01-2005 à 10:09:12    

Arjuna a écrit :

Truc qui manque dans tous les outils d'admin de base, où rarement complet (mise à par quelques exceptions peut-être)
 
1) Générer un document SQL contenant les objets sélectionnés (avec ou sans données). SQL Server le fait, sauf pour les données par exemple.
2) Capacité de gérer plusieurs bases de types différents à la fois (avoir dans une frame une base mySQL et dans une autre une base PostgreSQL par exemple)
3) Pouvoir interragir entre deux bases : dupliquer la structure et les données, comparer structure et données y compris quand ce sont 2 SGBD distincts.


 
1) mySql le fait il me semble, structure et / ou données.

Reply

Marsh Posté le 07-01-2005 à 11:33:14    

le fait d'exporter soit la structure de la table ou juste les données ou les deux en même temps.


Message édité par Berceker United le 07-01-2005 à 11:51:25
Reply

Marsh Posté le 07-01-2005 à 15:38:50    

J'ai acheté le livre SQL de chez CompusPress je crois que je vais y avoir tous les renseignements necessaire dedans, parait il qu'il est trop bon.
Pourquoi les différent SGDB ne respect pas le SQL stricte de base apres que chacun fasse ça sauce c'est leur probleme mais pourquoi?  
Pour mysql je comprend il faut pas demander autant a un produit gratuit et qui n'est pas baqulé donc les quelques defaut qu'il a je ne le juge pas par contre SQLserver & cie.

Reply

Marsh Posté le 07-01-2005 à 20:10:19    

Ca a déjà été discuté maintes fois.
 
Les SGBD ne respectent pas le SQL pour une raison initiale : la plupart existent depuis avant la création du standard. A cause de ça, ils traînent des boulets depuis cette époque.
La seconde raison, c'est aussi que les principes complexes du SQL ne sont pas toujours adaptables sur ces produits qui existent d'avant. Par conséquent, ils ont dû faire leur tambouille dans leur coin pour supporter les grandes principes, mais pas toujours la syntaxe exacte.
Et pour terminer, comme à l'époque de IE4 vs NS4, la plupart des SGBD intègrent souvent des principes qui ne sont pas encore standardisés, résultat, le standard ne correspond pas à ce qu'ils ont fait.
 
Sinon, mySQL est un produit bâclé, et c'est pour cette raison qu'il est aussi limité aujourd'hui.
Plus exactement, il l'était au départ. Je ne connais pas la génèse du truc, mais grossomodo, pour les petits systèmes, il n'y avait rien de performant à l'époque. Alors un gars, qui avait un besoin très limité d'un point de vue fonctionalité à décidé de se créer son propre SGBD, avec uniquement les fonctions lui étant nécessaires, mais par contre étant capable de tourner sur une machine légère tout en obtenant les mêmes perfs qu'un autre SGBD sur un gros serveur.
Il a gagné son pari, et à commencé à intéresser du monde, et la commnauté mySQL a commencé à exister à ce moment.
Ensuite, à l'époque des premiers hébergeurs gratuits proposant du PHP, il fallait trouver un SGBD très léger, capable de faire tourner une multitude de bases de petite taille, avec des besoins très simple, sans pour autant faire rammer les serveurs Unix utilisés à l'époque. Exit les gros SGBD du commerce donc, alors il se sont rabattus sur mySQL. C'est seulement depuis cette époque (et qu'il y a de véritables enjeux économiques derrière) que mySQL tente de devenir un produit plus complet.
 
A la base, il avait pour vocation d'être uniquement rapide, donc il n'a pas été conçu du tout pour être complexe, ce qui lui vaut son énorme retard sur la plupart des autres SGBD free d'un point de vue fonctionnel.

Reply

Marsh Posté le 07-01-2005 à 20:49:39    

Ok merci pour l'explication qui me parait logique. Dans le livre j'ai lus un peut l'évolution des SGDB et c'est différent type.
Une question.  
Actuellement sur mon projet je suis sur la génération de la document de la base. Soit les données, soit la structure.
Actuellement je l'exporte de différente maniere.

  • XML (je ne sais pas s'il y a une structure standars) avec génération possible et dynamiquement d'une DTD.
  • SQL (selon la syntaxe de chaque SGDB)
  • CSV
  • Excel
  • ???

J'aurais voulu savoir s'il y a un d'autre format d'exportation qui peuvent être utile?
Merci d'avance d'apporter vos experience et vos souhait


Message édité par Berceker United le 07-01-2005 à 21:33:53
Reply

Marsh Posté le 07-01-2005 à 23:32:18    

Quelques idées à froid :
- Fichier plat à pas fixe (afin d'être relu avec des accès record)
- Tableau HTML (à moins que tu ne fasses un XSL qui génère un tableau HTML à partir du XLS)
- Fichier backup (si le SGBD a une fonction de backup)
 
Pour le XML, je ne sais pas s'il y a une sructure standard, mais j'aime bien celle de SQL Server (simple et efficace) :
 

Code :
  1. /****** Object:  Table [dbo].[culture]    Script Date: 1/7/2005 11:31:46 PM ******/
  2. CREATE TABLE [dbo].[culture] (
  3. [id] [tinyint] IDENTITY (1, 1) NOT NULL ,
  4. [nom] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
  5. [rendement] [numeric](18, 0) NOT NULL ,
  6. [prixPlantation] [float] NOT NULL ,
  7. [delaisProduction] [numeric](18, 0) NOT NULL ,
  8. [dureeVie] [numeric](18, 0) NOT NULL
  9. ) ON [PRIMARY]
  10. GO
  11. select *
  12. from culture
  13. for xml auto
  14. <culture id="1" nom="Toutes fleurs" rendement="1" prixPlantation="1.000000000000000e+001" delaisProduction="0" dureeVie="5"/>
  15. <culture id="2" nom="Sapin" rendement="5" prixPlantation="1.000000000000000e+002" delaisProduction="5" dureeVie="50"/>
  16. ...


Message édité par Arjuna le 07-01-2005 à 23:32:49
Reply

Marsh Posté le 08-01-2005 à 00:56:35    

Arjuna a écrit :

Quelques idées à froid :
- Fichier plat à pas fixe (afin d'être relu avec des accès record)
- Tableau HTML (à moins que tu ne fasses un XSL qui génère un tableau HTML à partir du XLS)
- Fichier backup (si le SGBD a une fonction de backup)
 
Pour le XML, je ne sais pas s'il y a une sructure standard, mais j'aime bien celle de SQL Server (simple et efficace) :
 

Code :
  1. /****** Object:  Table [dbo].[culture]    Script Date: 1/7/2005 11:31:46 PM ******/
  2. CREATE TABLE [dbo].[culture] (
  3. [id] [tinyint] IDENTITY (1, 1) NOT NULL ,
  4. [nom] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
  5. [rendement] [numeric](18, 0) NOT NULL ,
  6. [prixPlantation] [float] NOT NULL ,
  7. [delaisProduction] [numeric](18, 0) NOT NULL ,
  8. [dureeVie] [numeric](18, 0) NOT NULL
  9. ) ON [PRIMARY]
  10. GO
  11. select *
  12. from culture
  13. for xml auto
  14. <culture id="1" nom="Toutes fleurs" rendement="1" prixPlantation="1.000000000000000e+001" delaisProduction="0" dureeVie="5"/>
  15. <culture id="2" nom="Sapin" rendement="5" prixPlantation="1.000000000000000e+002" delaisProduction="5" dureeVie="50"/>
  16. ...



 
Ok je comprend.
1- Pour le fichier a donnée a pas fixe j'ai pas compris. Désolé mais j'ai tous le vocabulaire :D, peut-tu m'expliquer?
 
2- Pour le tableau c'est prévus. En faite en creant un tableau HTML et en plaçant le type mime excel (je me rappelle plus trop de la syntaxe mais je ferais un edit) et c'est l'application excel qui va s'ouvrir avec les données de la table. Donc juste en changeant le type mime soit tu l'affiches en html sur le navigateur soit sur excel au format tableur. Je sais pas si tu m'as compris je m'enbrouille des fois.
 
3- pour la structure XML moi j'ai choisir cette structure.

Code :
  1. <db name="db_name">
  2.   <table_name>
  3.     <enregistrement num="1">
  4.       <champs1>...</champs>
  5.       <champs1>...</champs>
  6.       <champs1>...</champs>
  7.     </enregistrement>
  8.     <enregistrement num="2">
  9.       <champs1>...</champs>
  10.       <champs1>...</champs>
  11.       <champs1>...</champs>
  12.     </enregistrement>
  13.     ...
  14.   </table_name>
  15. </db>


En plus je génère une DTD dynamiquement.
Je pense que je vais proposer plusieurs type de structure.
 
Merci pour tes conseils. Je m'y penche.

Reply

Marsh Posté le 08-01-2005 à 23:06:58    

Utiliser des attributs pour le XML me semble bien mieu.
 
Je ne sais parcourir un fichier XML qu'en utilise MSXML, mais je suppose que les autres objets de parsing XML utilisent un système similaire.
 
Un tag XML est réprésenté dans un arbre par une Node, qui elle-même peut contenir des nodes et des attributs, ou un flux de données.
 
L'intérêt d'avoir les données dans les attributs, c'est que tu peux faire Node.Attributes[x].Value pour retrouver la valeur des champs, et tu es sûr et certain qu'il n'y a dedans que des données, il ne peut pas y avoir de sous-nodes (comme ça peut être le cas lors qu'on fait une requête qui retourne un résultat qui peut servir de regroupement).
 
C'est pas très clair. Un exemple :
 

Code :
  1. select utilisateur.login, champ.surface
  2. from champ, utilisateur
  3. where champ.proprio = utilisateur.id
  4. for xml auto
  5. <utilisateur login="MagicBuzz">
  6.    <champ surface="117"/>
  7.    <champ surface="182"/>
  8.    <champ surface="151"/>
  9.    <champ surface="127"/>
  10.    <champ surface="127"/>
  11.    <champ surface="112"/>
  12.    <champ surface="59"/>
  13. </utilisateur>
  14. <utilisateur login="Toto">
  15.    <champ surface="1903"/>
  16. </utilisateur>


Je ne commente pas le résultat, il coule de source ;)
(soit dit en passant, la génération de XML à partir de SQL Server c'est vraiment terrible :ouch:)

Reply

Marsh Posté le 08-01-2005 à 23:18:08    

Arjuna a écrit :

Utiliser des attributs pour le XML me semble bien mieu.
 
Je ne sais parcourir un fichier XML qu'en utilise MSXML, mais je suppose que les autres objets de parsing XML utilisent un système similaire.
 
Un tag XML est réprésenté dans un arbre par une Node, qui elle-même peut contenir des nodes et des attributs, ou un flux de données.
 
L'intérêt d'avoir les données dans les attributs, c'est que tu peux faire Node.Attributes[x].Value pour retrouver la valeur des champs, et tu es sûr et certain qu'il n'y a dedans que des données, il ne peut pas y avoir de sous-nodes (comme ça peut être le cas lors qu'on fait une requête qui retourne un résultat qui peut servir de regroupement).
 
C'est pas très clair. Un exemple :
 

Code :
  1. select utilisateur.login, champ.surface
  2. from champ, utilisateur
  3. where champ.proprio = utilisateur.id
  4. for xml auto
  5. <utilisateur login="MagicBuzz">
  6.    <champ surface="117"/>
  7.    <champ surface="182"/>
  8.    <champ surface="151"/>
  9.    <champ surface="127"/>
  10.    <champ surface="127"/>
  11.    <champ surface="112"/>
  12.    <champ surface="59"/>
  13. </utilisateur>
  14. <utilisateur login="Toto">
  15.    <champ surface="1903"/>
  16. </utilisateur>


Je ne commente pas le résultat, il coule de source ;)
(soit dit en passant, la génération de XML à partir de SQL Server c'est vraiment terrible :ouch:)


 
 
Je comprend ce que tu veux dire, ça va necessiter quelques petite manipulation de génération de XML et de la DTD(optionnel) mais c'est un bon défit de faire un outil qui permet de générer son xml. Je vais de toute façon plusieurs façon de présenter cela mais je crois que ça va être un peut chaud :/.


Message édité par Berceker United le 08-01-2005 à 23:29:26
Reply

Marsh Posté le 08-01-2005 à 23:18:28    

Sinon, un fichier à pas fixe sera pas exemple :
 

Code :
  1. CREATE TABLE user (
  2.     [nom] [varchar] (20) NOT NULL ,           -- 20 octets
  3.     [login] [varchar](20) NOT NULL          -- 20 octets
  4. )
  5. Si tu veux exporter cette table sous forme de fichier plat, ça donnera par exemple :
  6. [code]Sylvain             MagicBuzz           Jean-Edouard        Berceker United     (EOF)


[/code]
 
=> Chaque champ est exporté dans un fichier plat, sans délimiteur ni rien, mais il fait exactement la taille de son type. Deplus, le fichier est enregistré en binaire, donc un "int" fera par exemple 4 octets (32 bits).
 
En VB (et logiquement, tous les autres langages) on peut utiliser ce type de fichier en utilisant un type "structure" (ou "record" ) déclaré de la sorte :
 

Code :
  1. Struct user
  2.    nom as string*20
  3.    login as string*20
  4. End Struct


 
=> Ensuite, pour lire ou écrire dans le fichier, il suffit de faire un "get" ou un "put" en passant en paramètre une variable typée de la sorte.
 
Ca a le gros avantage d'être incomparablement plus rapide que n'importe quel autre type de fichier de données. Et ce, même pour seeker : puisque chaque record fait une taille fixe, si on veut aller au record 100, il suffit de seeker sur la position "sizeOf(user) * 100". Alors que pour un CSV par exemple, on n'a pas d'autre choix que de chercher 100 fois le caractère de saut de ligne, sans jamais savoir où le chercher : pour un grand volume de données, aller modifier la 500 000ème ligne devient impossible en CSV ou XML. Avec un fichier de la sorte, c'est à la fois extrêment rapide, et en plus ça ne consomme rien en mémoire.
Mieu encore, en une seule lecture, tous les membres de la structure son chargés (ou écrits sur le disque) et correctement typés. Bref, à côté du XML et du CSV, pour un batch d'intégration de données par exemple, y'a pas photo ! :)

Reply

Marsh Posté le 08-01-2005 à 23:34:45    

Je comprend et ça a l'air d'être très interessant mais ça marche seulement pour ceux qui ont une taille définit il y en a qui sont variable selon ce qu'il y a dedans.  Exemple le type TEXT de SQLSERVER.
 

Reply

Marsh Posté le 10-01-2005 à 01:28:54    

En effet, pour les champs de type text/image (ou long/blob sous Oracle), on a un problème.
A ce moment, je pense que tu peux simplement désactiver l'export de ces champs. De tout façon, dans un CSV ça ne marchera pas non plus, parceque tu peux très bien avoir des retour chariot dans ces types (tu me diras, dans un varchar aussi), mais surtout, les types image et blob sont binaires, donc pour du CSV c'est pas possible de les gérer. Seule le XML dans ce cas sera capable de les traîter correctement.
 
Sinon, tu peux traîter ces champs dans un tel type de fichier comme c'est géré en interne : écrire un "pointeur" (ce sera une adresse vers le début du lot de données, dans un fichier à part)
Par exemple, dans un tel fichier, tu va générer deux int64 pour ces types de champs.
Le premier va contenir la position du premier octets dans un second, et le second, la longueur. Dans ce fichier supplémentaire, tu n'auras alors que les valeurs de ces champs, les unes derrières les autres, sans séparateur non plus. Oracle et SQL Server gèrent ça plus ou moins de la même manière, puisqu'ils sont décrits comme des "pointeurs vers le fichier".
Il est aisé de coder une appli qui saura relire de tels fichiers, sans perte de l'intérêt de ce type de fichier (rapidité et légèreté de traîtement) :
 
Mettons une table avec un char(3), un varchar(20), puis deux blobs (pseudo code VB6)
 
Struct monRecord
   id as string*3
   nom as string*20
   blob1address int64
   blob1length int64
   blob2adress int64
   blob2length int64
End Struct
 
Dim ligne as monRecord
get #fileTable, ligne
Dim blob1 as byte[ligne.blob1length]
seek #fileData, ligne.blob1adress
get #fileData, blob1
Dim blob2 as byte[ligne.blob2length]
seek #fileData, ligne.blob2adress
get #fileData, blob2
 
=> En très peut de traîtements, tu as récupéré toute la ligne, et il n'existe pas à ma connaissance de façon plus rapide/légère en terme de charge de mémoire.


Message édité par Arjuna le 10-01-2005 à 01:29:50
Reply

Marsh Posté le 10-01-2005 à 01:31:02    

pour le length, d'ailleurs, un integer (32 bits) sera suffisant je pense. Car SQL Server en limité à 2 Go pour ces champs, et je pense qu'Oracle aussi.

Reply

Marsh Posté le 10-01-2005 à 02:01:22    

Sinon, moi je m'inqiéterais plus pour le problème du type NUMBER (ou DECIMAL). Car ca type, stocké sur jusqu'à 17 octets a une précision de 38 chiffres, là où un INT64 ou un FLOAT (8 octets) n'ont une précision que de 15 chiffres.
 
Cela dit, ces types, de par le structure, sont inadéquats pour calculs. On ne les trouve donc généralement que comme identifiants.
 
Et à moins qu'on veuille indexer dans une base de données chaque atôme de la Lune (on y est presque au niveau précision, à 10^3 près :D), c'est rare qu'on ait autant de ligne ;) 2^63 c'est déjà pas mal ;)
 
Mais bon, ce type me semble bien plus chaud à gérer proprement si on veut bien faire. Parceque là, on dépasse les capacités de l'ordinateur, et on doit se retrouver à faire des calculs sur des chaînes de caractères (à ma connaissance, les compilos actuels ne savent pas gérer de int128 (et de toute façon ça ne suffirait pas... seulement 16 octets, alors que NUMBER/DECIMAL sont sur 17 bits !)

Reply

Marsh Posté le 10-01-2005 à 02:27:54    

Houlala ! merci de toute ces explications. j'ai pas tous compris du premier coup mais en relisant ça commence a s'éclairer.:)
Si j'ai bien compris. en vulgarisant un peut :
 
data1[position] = xxx; data1[longueur] = xxx
data2[position] = xxx; data2[longueur] = xxx
data3[position] = xxx; data3[longueur] = xxx
 
data1.data2.data3

Reply

Marsh Posté le 10-01-2005 à 02:40:44    

cette fois, c'est moi qui n'ai rien compris :D
 
mais je pense que c'est ça ;)

Reply

Marsh Posté le 10-01-2005 à 02:45:11    

Arjuna a écrit :

cette fois, c'est moi qui n'ai rien compris :D
 
mais je pense que c'est ça ;)


En faite, les données sont l'un a la suite de l'autre sans séparateur et retour. ceci seront placé dans un fichier. Dans un autre fichier je place les pointeur ou coordonnée de chaque donnée c'est à dire position et longueur.
Comment je fais pour préciser qu'il vienne de tel ou tel champs?

Reply

Marsh Posté le 10-01-2005 à 02:45:46    

cette fois, c'est moi qui n'ai rien compris :D
 
mais je pense que c'est ça ;)

Reply

Marsh Posté le 10-01-2005 à 03:31:04    

Arjuna a écrit :

cette fois, c'est moi qui n'ai rien compris :D
 
mais je pense que c'est ça ;)


En faite, les données sont l'un a la suite de l'autre sans séparateur et retour. ceci seront placé dans un fichier. Dans un autre fichier je place les pointeur ou coordonnée de chaque donnée c'est à dire position et longueur.
Comment je fais pour préciser qu'il vienne de tel ou tel champs?

Reply

Marsh Posté le 10-01-2005 à 09:11:43    

Nope, c'est pas ça.
 
Dans ton fichier principal, tu as les champs "simples" stockés comme expliqué précédement.
Pour les blobs, tu enregistres dans ce fichier les "pointeurs" en question.
Et ensuite (en fait, en même temps) tu stockes dans un autre fichier les données BLOB de façon brute de fondrie.
 
Ainsi pour retrouver par exemple le blob qui correspond à la ligne 152, tu fais :
 
seek #file, 152
get #file, monRecord
seek #fileData, monRecord.positionBlob
dim dataBlob(monRecord.tailleBlob) as byte
get #fileData, dataBlob


Message édité par Arjuna le 10-01-2005 à 09:11:58
Reply

Marsh Posté le 10-01-2005 à 16:04:11    

Arjuna a écrit :

Nope, c'est pas ça.
 
Dans ton fichier principal, tu as les champs "simples" stockés comme expliqué précédement.
Pour les blobs, tu enregistres dans ce fichier les "pointeurs" en question.
Et ensuite (en fait, en même temps) tu stockes dans un autre fichier les données BLOB de façon brute de fondrie.
 
Ainsi pour retrouver par exemple le blob qui correspond à la ligne 152, tu fais :
 
seek #file, 152
get #file, monRecord
seek #fileData, monRecord.positionBlob
dim dataBlob(monRecord.tailleBlob) as byte
get #fileData, dataBlob


Sur la parti précedente j'ai compris mais sur la partie code ça me parle pas. je sais pas si j'ai bien compris.
Comment je peux determiner l'enregistrement 152 dans le fichier qui va contenir de données de type Blode?

Reply

Marsh Posté le 10-01-2005 à 17:38:34    

Tu vas lire dans le fichier qui contient les record simple.
A l'emplacement normal du blob, tu lis deux grands INT.
Le premier te donne la position du blob en question dans le fichier de données, et le second, sa taille (donc le nombre d'octets à lire).
 
D'où le :
 

Code :
  1. seek #fileData, monRecord.positionBlob
  2. dim dataBlob(monRecord.tailleBlob) as byte
  3. get #fileData, dataBlob


 
monRecord contient tous les champs de ta ligne, plus les deux int en question (positionBlob et tailleBlob).
Tu te positionnes alors dans le fichier de données (qui ne contient que les blobs) à la position "positionBlob", puis tu lis un array de bytes d'une taille "tailleBlob" depuis cette position. Tu as alors récupéré le blob correspondant à la ligne en question.

Reply

Marsh Posté le 10-01-2005 à 22:52:26    

Ok je comprend un peut mieux. Je vais pas trop m'ettendre sur ça, il faut que j'avance. Déjà le faite d'avoir trouvé le rowid m'enleve pas une épinde du pied mais bien un poutre du derriere ;).  
Je vais faire un autre post ou il y aura récapitulatif des conseil. S'il y en a d'autre n'hesite pas. ;)
Merci de tes contribution.

Reply

Marsh Posté le 11-01-2005 à 10:01:22    

C'est quoi le rowid alors ?

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed