Création de plusieurs Bases SQLite

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
ermar
Niveau 1
Niveau 1
Messages : 4
Enregistré le : mer. 09 sept. 2020 21:12
Status : Hors ligne

Création de plusieurs Bases SQLite

#1

Message par ermar »

Bonjour la communauté,
Après de multiples Tests et de lectures diverses, je n'arrive pas à trouver une solution et Je m'interroge si cela est vraiment réalisable.
Dans le cadre de mon travail, je cherche à traiter de petits fichiers CSV comme autant de petites bases de données afin d'extraire certaines informations.
L'objectif étant de pouvoir sélectionner ceux qui m'intéressent et le programme crée automatiquement les Tables et les remplit pour chaque base de données distinctes.
- Si je sélectionne 1 fichier, tout fonctionne correctement.
- A partir d'une sélection multiple de fichiers (Une boucle qui traite chaque fichier sélectionné), la 2eme Base ou N base ne se crée absolument pas.
J'ai l'impression qu'il ne veut traiter qu'une seule base dans mon programme et non plusieurs simultanément.
pourtant les fonctions _SQLite_Close() et _SQLite_Shutdown() sont indiquées à chaque nouveau traitement.

Pour exemple quelques lignes de codes pour illustrer mon soucis:
J'ai enchainé volontairement à la suite la création de 2 bases différentes (ce que fait mon programme lorsque j'ai sélectionné plusieurs fichiers à traiter)
- On constate que la 1ere Base est bien créée, mais jamais les suivantes.
#AutoIt3Wrapper_UseX64=Y ;(Y/N) Use AutoIt3_x64 or Aut2Exe_x64. Default=N
#include <File.au3>
#include <MsgBoxConstants.au3>
#include <SQLite.au3>
#include <SQLite.dll.au3>

; Init sqlite
_SQLite_Startup(@ScriptDir & "\sqlite3_x64.dll", False, 1) ; Load the DLL
If @error Then Exit MsgBox(0, "Error", "Unable to start SQLite, Please verify your DLL")
ConsoleWrite("SQlite version " & _SQLite_LibVersion() & @LF & @LF)

Local $hDskDb = _SQLite_Open()

If @error Then
    MsgBox($MB_SYSTEMMODAL, "SQLite Error", "Can't create a Database!")
    Exit -1
EndIf

;Premiere Base de donnée
msgbox(0,"base 1", $hDskDb);affichage qu'une base est bien créee en mémoire

 _SQLite_Exec($hDskDb, "create table XX (Key, FirstName text, LastName text, Birth text, Death text)")
_SQLite_Exec($hDskDb, "insert into XX values (10, 'Bohr', 'Niels', '1885/10/07', '1962/11/18')")
_SQLite_QueryFinalize($hDskDb)

_SQLite_Close()
_SQLite_Shutdown()

;Deuxième  Base de donnée

Local $hDB1 = _SQLite_Open()
If @error Then
    MsgBox($MB_SYSTEMMODAL, "SQLite Error", "Can't create a Database!")
EndIf

msgbox(0,"base 2", $hDB1);cette 2eme Base ou X base sera = à 0

_SQLite_Exec($hDB1, "create table TT (key, FirstName text, LastName text, Birth text)")
_SQLite_Exec($hDB1, "insert into TT values (10, 'Bohr', 'Niels', '1885/10/07')")

_SQLite_Close($hDB1)
_SQLite_Shutdown()
Je sèche complètement :-(
En vous remerciant par avance de l'aide que vous pourrez m'apporter, je vous souhaite une bonne soirée.
Cordialement

Eric
Avatar du membre
walkson
Modérateur
Modérateur
Messages : 1020
Enregistré le : ven. 12 août 2011 19:49
Localisation : Hurepoix
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#2

Message par walkson »

Bonjour,
Un petit exemple

Code : Tout sélectionner

#include <SQLite.au3>
#include <Array.au3>
Global $aResult, $iRows, $iColumns
	_SQLite_Startup("sqlite3.dll")
	$path = @ScriptDir & "\essay1.db"
	_SQLite_Open($path)
	$dll = _SQLite_LibVersion()
	If @error Then
		MsgBox($MB_SYSTEMMODAL, "SQLite Error: " & @error, _SQLite_ErrMsg() & "  Fin du programme " & @ScriptLineNumber)
		_SQLite_Close()
		_SQLite_Shutdown()
		Exit
	EndIf
$table = "CREATE TABLE IF NOT EXISTS   [Table_1] (  " & @CRLF
$table &= " [id] INTEGER PRIMARY KEY AUTOINCREMENT, " & @CRLF
$table &= " [AB] TEXT," & @CRLF
$table &= " [AC] TEXT," & @CRLF
$table &= " [AD] TEXT," & @CRLF
$table &= " [AA] TEXT);" & @CRLF
$table &= "Insert into Table_1 values (null,'A',108,109,'b');" & @CRLF

$table &= "CREATE TABLE IF NOT EXISTS   [Table_2] (" & @CRLF
$table &="  [id] INTEGER PRIMARY KEY AUTOINCREMENT," & @CRLF
$table &= " [AB] TEXT," & @CRLF
$table &= " [AC] TEXT," & @CRLF
$table &= " [AD] TEXT," & @CRLF
$table &= " [ss] TEXT);" & @CRLF
$table &= "Insert into Table_2 values (null,1,5,6,'a');" & @CRLF
$table &= "Insert into Table_2 values (null,'A',6,6,'b');" & @CRLF

$table &= "CREATE TABLE IF NOT EXISTS   [Table_3] (" & @CRLF
$table &="  [id] INTEGER PRIMARY KEY AUTOINCREMENT," & @CRLF
$table &= " [AB] CHAR," & @CRLF
$table &= " [AC] CHAR," & @CRLF
$table &= " [AD] TEXT," & @CRLF
$table &= " [ss] TEXT);"
	$rep = _SQLite_Exec(-1, $table)
	If $rep <> $SQLITE_OK Then
		MsgBox($MB_SYSTEMMODAL, "SQLite Error: " & @error, _SQLite_ErrMsg() & "  Fin du programme >>" & @ScriptLineNumber)
	EndIf
$iRval = _SQLite_GetTable2d(-1, "SELECT * FROM Table_2 ORDER BY Table_2.id DESC;", $aResult, $iRows, $iColumns)
_ArrayDisplay($aResult)
		_SQLite_Close()
		_SQLite_Shutdown()
		Exit
La recherche de la DLL varie selon les PC. Il faudra peut être modifier le début du code _SQLite_Startup("sqlite3.dll")
Cordialement,
Walkson
"Horas non numero nisi serenas " Le canon de midi
(Je ne compte que les heures heureuses)
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#3

Message par jchd »

Voir la réponse sur le forum US.
Pourquoi poster ici et là-bas ?
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
ermar
Niveau 1
Niveau 1
Messages : 4
Enregistré le : mer. 09 sept. 2020 21:12
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#4

Message par ermar »

Bonsoir,
Merci pour ce retour Walkson. J'y avais pensé mais je suis obligé de créer autant de bases différentes pour faciliter l'extraction des données par fichier traité, merci pour l'exemple.
Merci jchd, je comprends mieux. j'avais aussi posté sur le forum US car en informatique beaucoup de solutions sont résolues en Anglais et la communauté est plus nombreuse dans cette langue. Mais je préfère lire en français :-)

J'étais persuadé qu'il fallait clore chaque base de données pour en ouvrir une autre : je me suis trompé !
En supprimant les lignes _SQLite_Close() et _SQLite_Shutdown(), Ca fonctionne beaucoup mieux !

J'ai simplifié au maximum avec ce petit programme ci dessus.
Dans mon programme original, j'ai une fenêtre qui liste tous les fichiers susceptibles d'être analysés. Je sélectionne et le programme devait écrire chaque fichier correspondant à une base de donnée sauf que cela ne fonctionnait pas, voilà pourquoi je n'avais pas rajouté les lignes qui existaient à l'origine :
Exemple :
local $sDatabase = @ScriptDir & '\SQLite_Database.db'
Local $hDskDb = _SQLite_Open($sDatabase)

Néanmoins je m'interroge sur un point : _SQLite_Shutdown()

Mon programme reste "actif" , je fais rafraichir une GUI en sélectionnant une nouvelle source de répertoire pour lister de nouveaux fichiers à analyser, cela signifie que cette fonction ne doit être indiquée uniquement si je quitte définitivement mon application ? Car si je l'indique à la fin des traitements de mes fichiers, aucune base de donnée ne pourra être à nouveau créée avec ma nouvelle sélection si je comprends bien ?

Je tiens à vous remercier du temps que vous nous accordez pour nous aider à avancer. Je ne m'étais jamais penché sur SQLITE mais c'est sacrément puissant.

Eric
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#5

Message par jchd »

*_ShutDown ferme la DLL, il suffit de voir le code de cette fonction (d'où l'intérêt des includes sous forme source). Tout appel à une fonction SQLite_* suivant (outre *_StartUp) provoquera forcément une erreur par absence de la DLL en mémoire (d'où l'intérêt de tester le code erreur des fonctions qu'on invoque).

Le mieux est de coder carré :

Code : Tout sélectionner

#include <SQLite.au3>

Const $SQLITE_DLL = "C:\SQLite\bin\sqlite3.dll" ;<-- Change to the location of your sqlite dll

; Init sqlite
_SQLite_Startup($SQLITE_DLL, False, 1)
If @error Then Exit MsgBox($MB_ICONERROR, "SQLite Error", "Unable to start SQLite. Check existence of DLL")
OnAutoItExitRegister(_SQLite_Shutdown)

ConsoleWrite("SQlite version " & _SQLite_LibVersion() & @LF & @LF)	; optional!

Local $hDB = _SQLite_Open("AllFiles.sq3")
If @error Then Exit
OnAutoItExitRegister(SQ3Close)

... on se sert de SQLite
... et c'est tout.

Func SQ3Close()
	_SQLite_Close($hDB)
EndFunc
Si on doit ouvrir plusieurs bases et les conserver ouvertes, le plus simple est de créer un tableau global des handles des bases pour pourvoir tout fermer proprement dans SQ3Close().

Par contre, il subsiste deux questions: pourquoi ne pas utiliser une ou des bases sur disque, réutilisables ultérieurement ?
Autre point : si les .CSV ont la même structure, il serait préférable de tout stocker dans une seule base, avec une colonne indiquant de quel fichier .CSV chaque rangée provient. Ainsi on peut tout garder en mémoire, quelque soit le nombre de fichiers .CSV à gérer.
Dans ce cas et pour éviter une forte duplication (cf. normalisation SQL) il est judicieux de créer une table des fichiers :

Code : Tout sélectionner

CREATE TABLE "Fichiers" (
  "ID" INTEGER PRIMARY KEY, 
  "Fichier" CHAR NOT NULL);
et une table des données de tous les fichiers :

Code : Tout sélectionner

CREATE TABLE "CSVdata" (
  "ID" INTEGER PRIMARY KEY, 
  "FicID" INTEGER NOT NULL CONSTRAINT "fkDataFichier" REFERENCES "Fichiers"("ID") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, 
  "Col1" CHAR, 
  "Col2" CHAR, 
  "Col3" INT, 
  "Col4" CHAR);
avec une clé étrangère (foreign key) entre data et fichiers. Ne pas omettre le type attendu (affinité dans le cas de SQLite) de chaque colonne de donnée).

Par contre je m'inscris en faux contre le schéma proposé par walkson, car on ne peut pas paramétrer un nom de schéma (nom de table ou de colonne, par ex.) dans une requête SQL.

Oui, SQLite est extrêmement puissant (10 à 100 fois plus puissant que ce que laisse paraître la doc minimaliste de notre UDF, mais je n'ai pas trop le temps de me lancer dans une remise à plat complète) et aussi férocement véloce dans quasiment tous les cas.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
ermar
Niveau 1
Niveau 1
Messages : 4
Enregistré le : mer. 09 sept. 2020 21:12
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#6

Message par ermar »

Bonjour et merci JCHD pour ce retour.
Au départ effectivement j'aurais préféré tout mettre dans une seule base (merci pour le bout de code).
Les fichiers CSV peuvent avoir des Structures différentes :-( Dans mon programme je créé dynamiquement les Tables et les données en fonction de ce que je reçois. Pour le coup gérer une seule base unique devenait trop complexe.
- Je ne sais pas si j'aurais une utilisation ultérieure des bases (si je les écris dans un fichier) car l'objectif est de vérifier certains éléments en exécutant des requêtes SQL, donc je verrai au fil de mes besoins.

Néanmoins petite question, la fonction _SQLite_QueryFinalize doit être toujours utilisée après l'utilisation des _SQLite_Exec() ? Je regarde certains codes et cette fonction n'est pas forcément renseignée !?
Merci d'avance.
Eric
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#7

Message par jchd »

Cette fonction ne sert que si on utilise les fonctions de "bas niveau" qui retournent des données (*Query [donc select] + *FetchData + *Finalize) mais jamais suite à *Exec qui intègre tout ce qu'il faut pour n'exécuter que des commandes SQL qui ne renvoient pas un jeu de données (create, insert, update, drop, delete, pragma, ...).

D'ailleurs, l'exemple de *Query est complètement déconnant pour plusieurs raisons !
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
ermar
Niveau 1
Niveau 1
Messages : 4
Enregistré le : mer. 09 sept. 2020 21:12
Status : Hors ligne

[R] -Création de plusieurs Bases SQLite

#8

Message par ermar »

Merci jchd :-)
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: Création de plusieurs Bases SQLite

#9

Message par jchd »

Pour les requêtes, privilégier les fonctions de plus haut niveau :
_SQLite_GetTableData2D
_SQLite_GetTable2D
_SQLite_GetTable

Pour les autres commandes :
_SQLite_Exec
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Répondre