Script SQLPlus Oracle ==> Programme VB

Script SQLPlus Oracle ==> Programme VB - VB/VBA/VBS - Programmation

Marsh Posté le 02-09-2008 à 16:10:59    

Dans le cadre de mon boulot, j'utilise des scripts (sous forme de packages) que je lance sous SQLPlus (base Oracle) les uns après les autres à la main. Ces scripts contiennent de procédures qui utilisent des requêtes, des curseurs, etc, pour aller taper dans la base Oracle.
 
Comme c'est assez fastidieux, j'aimerais faire un programme VB qui reprendrait la structure de ces scripts, cependant je ne l'ai jamais fait et j'aimerais trouver des infos à ce sujet :
- Peut-on toujours utiliser des curseurs dans ce cadre ?
- Comment faire en sorte que mon programme communique avec ma base Oracle ?
 
Voilà, si vous connaissez un tutoriel sympa qui pourrait m'aider à répondre à ces questions et à celles que je serais suceptible de me poser je suis preneur. Merci d'avance :jap:


---------------
MyAnimeList
Reply

Marsh Posté le 02-09-2008 à 16:10:59   

Reply

Marsh Posté le 03-09-2008 à 09:23:27    

[:the panda]


---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 09:58:50    

VB est déprécié, je te conseille donc VB.NET ou C#, qui sont les "suites" proposées par Microsoft et dont il existe tous les outils gratuits pour travailler.
 
Pour l'accès aux données, tu passeras par un connecteur .NET qui ressemble d'un point de vue programmation comme deux goutes d'eau aux drivers ODBC ou OLEDB. Tu peux donc faire des curseurs, des transactions, et à tout ce que tu veux.
 
Les limitations sont cependant (non exhaustif) les suivantes :
- Impossibilité (ou presque) de se créer une variable Oracle et la réutiliser plus tard dans une autre requête.
- Impossibilité d'utiliser un script PL/SQL directement, il faut en faire une PS Oracle et lancer la PS.
- Un certain nombre de types Oracle ne sont pas aisés à utiliser, à commencer par les blob/clob, mais aussi le number (Oracle permet de stocker plus de chiffres dans un Number que ne permet .NET dans un decimal, ce qui provoque des problèmes parfois)
 
Pour le reste, tout fonctionne parfaitement bien.
 
Voici un exemple de ce qu'on peut faire par exemple (ici, succession de requêtes au sein d'une transaction, avec proposition de commit ou rollback une fois les requêtes effectuées) :
 

Code :
  1. private const string sqlUpdateAdrress = "update adr set codtrn = :codtrn, sigtra = :sigtra where exists (select null from lad where lad.codsoc = :codsoc and lad.typtie = 'CLI' and lad.sigtie = :sigtie and adr.codsoc = lad.codsoc and adr.typtie = lad.typtie1 and adr.sigadr = lad.sigadr and adr.typadr = lad.typadr1 and adr.numadr = lad.numadr1 and adr.codtrn = :oldtrn)";
  2.        private const string sqlUpdateCde = "update eve set codtrn = :codtrn where codsoc = :codsoc and achvte = 'V' and typeve = 'CDV' and codeta in ('V', 'I') and sigtie = :sigtie and codtrn = :oldtrn";
  3.        private const string sqlUpdateCdp = "update evl set evl.codtrn = :codtrn where evl.codsoc = :codsoc and evl.achvte = 'V' and evl.typeve = 'CDV' and    evl.codtrn = :oldtrn and evl.numeve in (select eve.numeve from eve where eve.codsoc = evl.codsoc and eve.achvte = evl.achvte and eve.typeve = evl.typeve and eve.codeta in ('V', 'I') and eve.sigtie = :sigtie)";
  4.        private const string sqlUpdateLie = "update eve set codtrn = :codtrn where codsoc = :codsoc and achvte = 'V' and typeve = 'LIV' and codeta in ('V', 'C') and sigtie = :sigtie and codtrn = :oldtrn";
  5.        private const string sqlUpdateLip = "update evl set evl.codtrn = :codtrn where evl.codsoc = :codsoc and evl.achvte = 'V' and evl.typeve = 'LIV' and    evl.codtrn = :oldtrn and evl.numeve in (select eve.numeve from eve where eve.codsoc = evl.codsoc and eve.achvte = evl.achvte and eve.typeve = evl.typeve and eve.codeta in ('V', 'C') and eve.sigtie = :sigtie)";
  6.  
  7.        private void button1_Click(object sender, EventArgs e)
  8.        {
  9.            if (comboBox1.SelectedValue != null && comboBox2.SelectedValue != null && comboBox3.SelectedValue != null && comboBox4.SelectedValue != null && comboBox5.SelectedValue != null)
  10.            {
  11.                OracleConnection cnx = new OracleConnection(Tournees.Properties.Settings.Default.ConnectionString);
  12.                OracleTransaction trans;
  13.                OracleCommand cmd;
  14.                cnx.Open();
  15.  
  16.                trans = cnx.BeginTransaction();
  17.  
  18.                cmd = cnx.CreateCommand();
  19.  
  20.                cmd.CommandType = CommandType.Text;
  21.                cmd.Transaction = trans;
  22.  
  23.                OracleParameter codsoc = cmd.CreateParameter();
  24.                codsoc.Direction = ParameterDirection.Input;
  25.                codsoc.OracleType = OracleType.Number;
  26.                codsoc.ParameterName = "codsoc";
  27.                codsoc.Value = (decimal)comboBox4.SelectedValue;
  28.  
  29.                OracleParameter sigtie = cmd.CreateParameter();
  30.                sigtie.Direction = ParameterDirection.Input;
  31.                sigtie.OracleType = OracleType.NVarChar;
  32.                sigtie.ParameterName = "sigtie";
  33.                sigtie.Value = (string)comboBox1.SelectedValue;
  34.  
  35.                OracleParameter oldtrn = cmd.CreateParameter();
  36.                oldtrn.Direction = ParameterDirection.Input;
  37.                oldtrn.OracleType = OracleType.NVarChar;
  38.                oldtrn.ParameterName = "oldtrn";
  39.                oldtrn.Value = (string)comboBox2.SelectedValue;
  40.  
  41.                OracleParameter codtrn = cmd.CreateParameter();
  42.                codtrn.Direction = ParameterDirection.Input;
  43.                codtrn.OracleType = OracleType.NVarChar;
  44.                codtrn.ParameterName = "codtrn";
  45.                codtrn.Value = (string)comboBox3.SelectedValue;
  46.  
  47.                OracleParameter sigtra = cmd.CreateParameter();
  48.                sigtra.Direction = ParameterDirection.Input;
  49.                sigtra.OracleType = OracleType.NVarChar;
  50.                sigtra.ParameterName = "sigtra";
  51.                sigtra.Value = (string)comboBox5.SelectedValue;
  52.  
  53.                cmd.Parameters.Clear();
  54.                cmd.CommandText = sqlUpdateAdrress;
  55.  
  56.                cmd.Parameters.Add(codsoc);
  57.                cmd.Parameters.Add(sigtie);
  58.                cmd.Parameters.Add(oldtrn);
  59.                cmd.Parameters.Add(codtrn);
  60.                cmd.Parameters.Add(sigtra);
  61.  
  62.                int nbAdr = cmd.ExecuteNonQuery();
  63.  
  64.                cmd.Parameters.Clear();
  65.                cmd.CommandText = sqlUpdateCde;
  66.  
  67.                cmd.Parameters.Add(codsoc);
  68.                cmd.Parameters.Add(sigtie);
  69.                cmd.Parameters.Add(oldtrn);
  70.                cmd.Parameters.Add(codtrn);
  71.  
  72.                int nbCde = cmd.ExecuteNonQuery();
  73.  
  74.                cmd.Parameters.Clear();
  75.                cmd.CommandText = sqlUpdateCdp;
  76.  
  77.                cmd.Parameters.Add(codsoc);
  78.                cmd.Parameters.Add(sigtie);
  79.                cmd.Parameters.Add(oldtrn);
  80.                cmd.Parameters.Add(codtrn);
  81.  
  82.                int nbCdp = cmd.ExecuteNonQuery();
  83.  
  84.                cmd.Parameters.Clear();
  85.                cmd.CommandText = sqlUpdateLie;
  86.  
  87.                cmd.Parameters.Add(codsoc);
  88.                cmd.Parameters.Add(sigtie);
  89.                cmd.Parameters.Add(oldtrn);
  90.                cmd.Parameters.Add(codtrn);
  91.  
  92.                int nbLie = cmd.ExecuteNonQuery();
  93.  
  94.                cmd.Parameters.Clear();
  95.                cmd.CommandText = sqlUpdateLip;
  96.  
  97.                cmd.Parameters.Add(codsoc);
  98.                cmd.Parameters.Add(sigtie);
  99.                cmd.Parameters.Add(oldtrn);
  100.                cmd.Parameters.Add(codtrn);
  101.  
  102.                int nbLip = cmd.ExecuteNonQuery();
  103.  
  104.                cmd.Dispose();
  105.  
  106.                if (MessageBox.Show(this, string.Format("{0} adresse(s) mise(s) à jour\n{1} commande(s) mise(s) à jour\n{2} poste(s) de commandes mis à jour\n{3} livraison(s) mise(s) à jour\n{4} poste(s) de livraisons mis à jour", nbAdr, nbCde, nbCdp, nbLie, nbLip), "Confirmez-vous les modifications ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
  107.                {
  108.                    trans.Commit();
  109.                    this.aDRTableAdapter.Fill(this.dataSetTrnActuelles.ADR, (decimal)comboBox4.SelectedValue, (string)comboBox1.SelectedValue);
  110.                }
  111.                else
  112.                {
  113.                    trans.Rollback();
  114.                    MessageBox.Show("Annulation effectuée" );
  115.                }
  116.                trans.Dispose();
  117.  
  118.                cnx.Close();
  119.                cnx.Dispose();
  120.            }
  121.            else
  122.            {
  123.                MessageBox.Show(this, "Tous les champs ne sont pas correctement remplis", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
  124.            }
  125.        }

Reply

Marsh Posté le 03-09-2008 à 10:10:11    

Je n'ai que VB6 de disponible :/
 
Par contre je me pose une question : est-ce qu'il est possible de lancer des procédures incluses dans des packages comme si je le faisais sous SQLPlus à partir d'une fonction ?
 
Par exemple : exec pck_package.procédure(params)


---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 10:12:17    

oui sans problème
 
ton commandtext de ton objet commande sera "pck_package.procédure" et son commandtype sera "storedprocedure".
 
et tu ajouteras les parameters de la même façon que dans mon exemple.
 
ps : en VB6 même si le langage n'a rien à voir et que tu passes par DAO et non la couche .NET, y'a presque rien à changer par rapport au code que j'ai posté (même attributs et métodes d'objets pour la plupart). c'est pour ça que je me permet d'insister.
VS 2008 C# Express est gratuit et utilisable à des fins professionnelles et lucratives.
 
http://msdn.microsoft.com/fr-fr/express/aa975050.aspx

Message cité 1 fois
Message édité par MagicBuzz le 03-09-2008 à 10:14:49
Reply

Marsh Posté le 03-09-2008 à 10:13:07    

MagicBuzz a écrit :

oui sans problème
 
ton commandtext de ton objet commande sera "pck_package.procédure" et son commandtype sera "storedprocedure".
 
et tu ajouteras les parameters de la même façon que dans mon exemple.


 
ok merci, je vais voir ça :jap:


---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 10:57:57    

Pour l'instant j'essaie de trouver comment me connecter à ma base Oracle via ODBC et en cherchant un peu sur Internet je retrouve souvent cette déclaration :
Public db As New ADODB.Connection
 
Sauf qu'à l'exécution il me dit que ce n'est pas un type défini. J'imagine qu'il faut que je récupère un fichier de déclaration quelque part pour l'inclure dans mon projet mais je ne sais pas où le trouver. une idée ? :/  
 
EDIT : à chaque fois que je tombe sur un lien qui utilise cette expression, j'ai l'impression qu'ils considèrent que le type ADODB.Connection est déjà acquis de base.


Message édité par Kirvel le 03-09-2008 à 10:59:17

---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 11:06:42    

tu dois lier à ton projet "microsoft data object 2.6" ou un truc du genre (DAO.dll)

Reply

Marsh Posté le 03-09-2008 à 11:07:26    

(dans le menu "projet" tu à un menu pour gérer les dépendences du projet. ça fait longtemps que j'ai pas touché vb, donc je ne me souviens plus des noms exacts ;))

Reply

Marsh Posté le 03-09-2008 à 11:17:58    

nickel merci :jap:
 
C'est dans Projet/Références, il faut cocher "Microsoft ActiveX Data Object 2.6 Library"


---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 11:17:58   

Reply

Marsh Posté le 03-09-2008 à 11:42:21    

a mettre dans tes bookmarks pour avoir de la doc sur ADO :
 
http://www.devguru.com/technologies/ado/home.asp

Reply

Marsh Posté le 03-09-2008 à 16:10:32    

Merci pour ton aide, j'arrive à lancer mes procédures ça rox [:bien]
 
Par contre j'ai petit souci qui risque de bien me bloquer, c'est que ces procédures contiennent des étapes qui auparavant s'enchaînaient, mais qu'il a fallu découper pour pouvoir bidouiller des trucs à la main dans la base avant de lancer les étapes suivantes. Si ç'avaient été des procédures distinctes il n'y aurait pas eu de souci, sauf que là pour dire "STOP ON S'ARRÊTE ICI !" ils ont trouvé la judicieuse idée de foutre un RAISE_APPLICATION_ERROR avec un message.
 
Quand la procédure arrive à ce stade, mon programme s'arrête avec un pop-up qui contient le message en question (ça c'est cool), mais il me propose "Débogage" ou "Fin" (ça c'est moins cool). Le truc c'est que j'aimerais faire un EXIT SUB juste après le lancement de ma procédure pour pouvoir trifouiller la base à la main sans avoir à arrêter l'exécution de mon programme, puisqu'il y a encore des étapes à lancer derrière :/
Comment pourrais-je contourner ce problème à part en réécrivant la procédure stockée ? tâche qui s'avèrerait fastidieuse :/
 
EDIT : exemple :

Code :
  1. IF param <= 5 THEN
  2.         REPRISE_JOURNAUX;
  3.       END IF;
  4.       IF param <= 6 THEN
  5.         REPRISE_FOURNISSEURS;
  6.         RAISE_APPLICATION_ERROR(-20101, 'AP FOUR', FALSE);
  7.       END IF;
  8.       IF param <= 7 THEN
  9.         REPRISE_NATURES;
  10.       END IF;


Ici on a lancé la procédure en passant un param >= 6, puis on stop après la reprise_fournisseur pour trifouiller des trucs. Une fois que c'est fait, on relance cette procédure en passant param = 7 pour enchainer. Ce que je voudrais c'est que mon programme ne plante pas quand j'ai un RAISE_APPLICATION_ERROR, c'est possible ?


Message édité par Kirvel le 03-09-2008 à 16:24:14

---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 16:25:32    

Code :
  1. ' début du code ici
  2.  
  3. on error resume next
  4.  
  5. ' fait un truc qui risque de planter
  6.  
  7. if err <> 0 then
  8.  msgbox("proutch " & err.message)
  9.  err.clear
  10. end if
  11.  
  12. on error goto 0
  13.  
  14. ' suite du code ici

Reply

Marsh Posté le 03-09-2008 à 16:31:12    

MagicBuzz a écrit :

Code :
  1. ' début du code ici
  2.  
  3. on error resume next
  4.  
  5. ' fait un truc qui risque de planter
  6.  
  7. if err <> 0 then
  8.  msgbox("proutch " & err.message)
  9.  err.clear
  10. end if
  11.  
  12. on error goto 0
  13.  
  14. ' suite du code ici



 
ah mais ouais j'avais oublié ça, sainxeulote


---------------
MyAnimeList
Reply

Marsh Posté le 03-09-2008 à 16:38:47    

attention cependant. si tu produit une erreur, vérifie que le rollback se produit comme lorsque tu es avec sql+, rien n'est moins sûr.
 
et si l'ensemble de la procédure doit être transactionnelle, n'oublie pas d'utiliser l'objet transaction sur tes commandes et bien faire un begintrans au début et commit/rollback à la fin.
 
parceque dans sql+ il suffit de ne pas commit pour faire le rollback à la sortie, alors qu'avec ADO, le commit est implicite à chaque instruction, il faut donc faire une transaction globale pour reproduire le fonctionnement de sql+ ;)

Message cité 1 fois
Message édité par MagicBuzz le 03-09-2008 à 16:39:47
Reply

Marsh Posté le 03-09-2008 à 16:57:09    

MagicBuzz a écrit :

attention cependant. si tu produit une erreur, vérifie que le rollback se produit comme lorsque tu es avec sql+, rien n'est moins sûr.
 
et si l'ensemble de la procédure doit être transactionnelle, n'oublie pas d'utiliser l'objet transaction sur tes commandes et bien faire un begintrans au début et commit/rollback à la fin.
 
parceque dans sql+ il suffit de ne pas commit pour faire le rollback à la sortie, alors qu'avec ADO, le commit est implicite à chaque instruction, il faut donc faire une transaction globale pour reproduire le fonctionnement de sql+ ;)


Je vois [:transparency]
Ceci dit pour ce processus-là je n'avais aucun commit à faire sous SQLPlus, j'ai pas vérifié mais les commit/rollback doivent déjà être gérés dans la procédure. [:cosmoschtroumpf]


---------------
MyAnimeList
Reply

Sujets relatifs:

Leave a Replay

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