Extraction de Script SQL - John COLIBRI. |
- résumé : Comment générer un script SQL à partir d'une base de données Interbase / Firebird
- mots clé : script SQL - Interbase - Firebird - IbExtract
- logiciel utilisé : Windows XP personnel, Delphi 6.0
- matériel utilisé : Pentium 2.800 Mhz, 512 Meg de mémoire, 250 Giga disque dur
- champ d'application : Delphi 1 à 2006, Turbo Delphi sur Windows
- niveau : développeur Delphi - développeur Interbase
- plan :
1 - Introduction Cet article va indiquer comment extraire d'une base de données existante un
script SQL capable de recréer la même base. Cet utilitaire permet: - de sauvegarder de façon lisible (mais verbeuse) les données d'une base
- de porter facilement les données d'une version d'un même moteur à une autre version
- d'adapter et modifier les données pour les porter sur un autre moteur, ou changer son fonctionnement (passer du dialecte Interbase 1 au dialecte 3)
- de changer la structure de la base, ou la valeur des données
- de documenter la base (en utilisant des outils de génération de documentation à partir du script)
Nous avons utilisé cet utilitaire dans notre article sur
MastApp, la base de démonstration de Delphi
2 - Principe Nous pouvons utiliser plusieurs techniques:
- analyser les tables système qui contiennent tout les informations sur la base
- utiliser des composants Delphi qui sont capables d'extraire le schéma
- utiliser des outils externes tels que IbExpert
Comme Delphi fournit, depuis Delphi 6, un composant spécifique d'extraction de schéma pour Interbase, nous avons opté pour cette technique-là. Notez que si nous souhaitions effectuer une extraction directe à partir des tables
système, un moyen commode serait d'examiner le code source d'Ibx et d'adapter ce code pour nos propres besoins. Dans notre cas, le composant IbExtract donne satisfaction, et nous nous contenterons de l'utiliser
3 - Le Projet Delphi 3.1 - L'Objectif Nous devons créer un script qui permettra : - de créer les tables ainsi que toutes leurs annexes (générateurs, triggers etc)
- de remplir les données des tables
3.2 - Le composant IbExtract Ce composant a été construit uniquement pour extraire les données d'une base.
Je suppose que Jeff OVERCASH l'a spécialement créé pour écrire IbConsole. Il devrait donc nécessairement permettre de réaliser notre travail. Le principal problème à résoudre est de trouver les paramètres à utiliser.
La documentation indique que - la syntaxe de base est:
nous appelons Extract de la façon suivante:
type TExtractObjectTypes= (eoDatabase, eoDomain, eoTable,
eoView, eoProcedure, eoFunction, eoGenerator,
eoException, eoBLOBFilter, eoRole, eoTrigger,
eoForeign, eoIndexes, eoChecks, eoData);
TExtractType= (etDomain, etTable, etRole, etTrigger,
etForeign, etIndex, etData, etGrant,
etCheck, etAlterProc);
TExtractTypes= Set of TExtractType;
procedure ExtractObject(ObjectType: TExtractObjectTypes;
ObjectName: String; ExtractTypes: TExtractTypes); |
- les paramètres sont:
- le type de donnée à extraire: eoDomain pour les domaines, eoTable pour les tables etc
- si nous ciblons un objet particulier (une table, une procédure cataloguée etc), le nom de cet objet
- pour un objet donnée, le dernier paramètre spécifie quelle donnée (par exemple pour une table, le triggers en utilisant etTrigger)
En ce qui nous concerne, nous espérions pouvoir tout extraire (les requêtes de
création de tables, les triggers etc et les données) par:
IbExtract1.ExtractObject(eoDataBase, '', []); |
mais cet appel fournit bien le script de toutes les créations, mais pas le script pour les données. Après quelques essais, l'appel:
IbExtract1.ExtractObject(eoTabke, 'orders', [etData]); |
fournit bien le script des données de la table ORDERS, mais aussi au début le script de création de cette table. En combinant les deux appels, nous obtenons finalement notre résultat.
3.3 - Le code d'extraction du schéma
Voici le projet: | créez une nouvelle application Delphi et renommez-la "p_extract_ib_script" |
| ajoutez un tMemo qui recevra le script du schéma | |
de la page "Interbase" de la Palette, sélectionnez IbTransaction et posez-le sur la Forme | |
de la page "Interbase" de la Palette, sélectionnez IbDataBase et posez-le sur la Forme | |
reliez IbTransaction1 et IbDataBase1 | | double cliquez sur IbDatabase1 pour afficher l'Editeur de Connection.
Remplissez le nom de la base, le nom de l'utilisateur, le mot de passe (SYSDBA), décochez "LoginPrompt":
Cliquez "Ok" pour sauvegarder, double-cliquez à nouveau et sélectionnez "Test" pour vérifier la connection | |
de l'onglet "Interbase" de la Palette sélectionnez IbExtract et posez-le sur la Forme |
| posez un tButton sur la Forme, renommez-le "complete_schema_", créez son événement OnClick et écrivez le code qui extrait toutes les requêtes de création du schéma:
procedure TForm1.complete_schema_Click(Sender: TObject);
begin open_database_Click(Nil);
with IBExtract1 do begin
ExtractObject(eoDataBase, '', []);
Memo1.Lines.Assign(Items); end;
end; // complete_schema_Click | | |
compilez, exécutez et cliquez "complete_schema_" | | le schéma complet s'affiche dans Memo1 |
3.4 - Le code d'extraction des données Pour extraire les données, nous allons procéder en deux étapes: - trouver le nom de toutes les tables
- pour chaque table, appeler ExtractObject avec le paramètres etData
L'extraction des noms de Table est réalisé en appelant la procédure d'extraction complète ci-dessus, et en extrayant le nom situé après chaque CREATE DATABASE .
Voici comment placer le nom de chaque Table dans une tListBox: | ajoutez une tListBox au projet |
| ajoutez un tButton, renommez-le "tables_", et tapez le code qui utilise ExtractObject pour récupérer le script de création et en extrait les noms de tables:
procedure TForm1.tables_names_Click(Sender: TObject);
var l_item: Integer;
l_the_line: String; l_index: Integer;
l_table_name: String; begin
open_database_Click(Nil); ListBox1.Clear;
with IBExtract1 do begin
ExtractObject(eoTable, '', []);
with Items do
for l_item:= 0 to Count- 1 do
begin
l_the_line:= Trim(Strings[l_item]);
if Pos('CREATE TABLE', l_the_line)= 1
then begin
System.Delete(l_the_line, 1, Length('CREATE TABLE'));
l_index:= 1;
l_table_name:=
f_string_extract_non_blank(l_the_line, l_index);
ListBox1.Items.Add(l_table_name);
end; end;
end; end; // tables_names_Click | |
| ajoutez un tButton, renommez-le "all_table_data_", et tapez le code qui utilise ExtractObject pour récupérer le script d'insertion de données pour chaque Table:
procedure generate_insert_into(p_table_name: String;
p_c_strings: tStrings);
var l_item_index: Integer;
l_the_line: String; begin
with Form1, IBExtract1 do
begin
ExtractObject(eoTable, p_table_name, [etData]);
// -- skip the schema
with Items do begin
l_item_index:= 0;
while l_item_index< Count do
begin
l_the_line:= Strings[l_item_index];
if Pos('INSERT INTO', l_the_line)> 0
then Break
else Inc(l_item_index);
end; // -- now get the INSERT INTO
while l_item_index< Count do
begin
l_the_line:= Strings[l_item_index];
p_c_strings.Add(l_the_line);
Inc(l_item_index);
end; // while l_item_index
end; // with Items
end; // with IBExtract1 end; // generate_insert_into
procedure TForm1.all_table_data_Click(Sender: TObject);
var l_item_index: Integer; begin
with ListBox1 do
for l_item_index:= 0 to Count- 1 do
generate_insert_into(Items[l_item_index],
Memo1.Lines);
end; // all_table_data_Click | | |
compilez, exécutez et cliquez "complete_schema_" | | voici une vue du projet: <IMG SRC="_i_image.png" align=middle alt="image"> |
| compilez, exécutez et cliquez "all_table_data_" | |
voici une vue du projet, avec le script pour PARTS: ![image](http://www.jcolibri.com/articles/bdd/interbase/sql_script_extraction/_i_image/ibex_extract_interbase_script.png) |
4 - Télécharger le code source Delphi Vous pouvez télécharger: - extract_script.zip : le projet qui extrait le script du schéma et
d'insertion de données d'une base (22 K)
Ce .ZIP qui comprend: - le .DPR, la forme principale, les formes annexes eventuelles
- les fichiers de paramètres (le schéma et le batch de création)
- dans chaque .ZIP, toutes les librairies nécessaires à chaque projet (chaque .ZIP est autonaume)
Ces .ZIP, pour les projets en Delphi 6, contiennent des chemins RELATIFS. Par conséquent:
- créez un répertoire n'importe où sur votre machine
- placez le .ZIP dans ce répertoire
- dézippez et les sous-répertoires nécessaires seront créés
- compilez et exécutez
Ces .ZIP ne modifient pas votre PC (pas de changement de la Base de Registre, de DLL ou autre). Pour supprimer le projet, effacez le répertoire. La notation utilisée est la notation alsacienne qui consiste à préfixer les
identificateurs par la zone de compilation: K_onstant, T_ype, G_lobal, L_ocal, P_arametre, F_unction, C_lasse. Elle est présentée plus en
détail dans l'article La Notation Alsacienne
Comme d'habitude:
- nous vous remercions de nous signaler toute erreur, inexactitude ou problème de téléchargement en envoyant un e-mail à jcolibri@jcolibri.com. Les corrections
qui en résulteront pourront aider les prochains lecteurs
- tous vos commentaires, remarques, questions, critiques, suggestion d'article, ou mentions d'autres sources sur le même sujet seront de même
les bienvenus à jcolibri@jcolibri.com.
- plus simplement, vous pouvez taper (anonymement ou en fournissant votre e-mail pour une réponse) vos commentaires ci-dessus et nous les envoyer en
cliquant "envoyer" :
- et si vous avez apprécié cet article, faites connaître notre site,
ajoutez un lien dans vos listes de liens ou citez-nous dans vos blogs ou réponses sur les messageries. C'est très simple: plus nous aurons de visiteurs et de références Google, plus nous écrirons d'articles.
5 - L'auteur John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le
conseil (composants, architecture, test) et la
formation. Son site contient des articles
avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et
UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client. |