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

PL/SQL Oracle Discussion :

Optimisation du code


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2011
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2011
    Messages : 60
    Par défaut Optimisation du code
    Bonjour,

    Etant débutant en PL/SQL, j'aimerais avoir votre avis sur mon code.
    Des optimisations sont-elles possibles ?

    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
    17
    18
    CREATE OR REPLACE PACKAGE BODY pkg_test IS
     
      PROCEDURE query_test (table1 IN VARCHAR2, table2 IN VARCHAR2) IS
     
    query_max VARCHAR2(100);
    	max_q   VARCHAR2(100);
    	collection_query  VARCHAR2(3500);
     
      BEGIN
     	query_max := 'SELECT max(num) FROM ' || table2;
    EXECUTE IMMEDIATE query_max  INTO max_q;
     
    collection_query := 'INSERT INTO ' || table2 || ' (SELECT num FROM '|| table1 ||' WHERE num > :1)';    
    	EXECUTE IMMEDIATE collection_query USING max_q;
     
      END;
     
    END;
    Je n'ai pas réussi à la faire fonctionner en remplaçant le premier EXECUTE IMMEDIATE par une requête sous la forme SELECT.. INTO.. FROM table2.
    table2 me pose problème dans ce cas.

    Merci d'avance

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 953
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Citation Envoyé par alex_972 Voir le message
    Je n'ai pas réussit à la faire fonctionner en remplaçant le premier EXECUTE IMMEDIATE par une requête sous la forme SELECT.. INTO.. FROM table2.
    C'est normal le INTO se fait bien dans le EXECUTE IMMEDIATE.
    Par contre je ne sais pas dans quel contexte cette procédure est utilisée mais la concaténation de chaines de caractères représente un risque d'injection SQL.
    Comme pour les noms de tables, colonnes, il n'est bien évidemment pas possible de binder, il faut alors utiliser le package DBMS_ASSERT, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    query_max := 'SELECT max(num) FROM ' || dbms_assert.simple_sql_name(table2);
    Sinon perso j'aurais mis le SELECT MAX directement dans la requête INSERT.
    Et si num est bien un numérique, il ne faut pas le fetch dans un varchar2 afin d'éviter des conversions implicites.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2011
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2011
    Messages : 60
    Par défaut
    Merci skuatamad pour ta réponse.

    Je ne connaissais pas DBMS_ASSERT. Y a-t-il d'autre chose à savoir sur l'injection SQL lors de la programmation en PL/SQL ?

    Pour le select dans l'Execute immediate, c'est ce que j'ai fait au début mais je me demandais si ce n'étais pas plus propre comme çà.

    Concernant la colonne num, c'est un timestamp. (la requete originale fait une bonne centaine de ligne

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2011
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2011
    Messages : 60
    Par défaut
    Est-il possible d'appliquer dbms_assert.simple_sql_name() une seule fois sur la variable de ma procédure ? Ca me permettrait d'éviter d'utiliser cette fonction X fois.

    Quelque chose dans ce genre :
    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
    17
    18
    19
    CREATE OR REPLACE PACKAGE BODY pkg_test IS
     
      PROCEDURE query_test (table1 IN VARCHAR2, table2 IN VARCHAR2) IS
    
            table2 VARCHAR2(100) := dbms_assert.simple_sql_name(table2);
    
    	max_q   VARCHAR2(100);
    	collection_query  VARCHAR2(3500);
     
      BEGIN
     	
    EXECUTE IMMEDIATE  'SELECT max(num) FROM ' || table2  INTO max_q;
     
    collection_query := 'INSERT INTO ' || table2 || ' (SELECT num FROM '|| table1 ||' WHERE num > :1)';    
    	EXECUTE IMMEDIATE collection_query USING max_q;
     
      END;
     
    END;
    Là, j'ai une belle erreur duplicate field.

  5. #5
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 953
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Y a-t-il d'autre chose à savoir sur l'injection SQL lors de la programmation en PL/SQL ?
    Utiliser USING pour les valeurs des colonnes.
    Concernant la colonne num, c'est un timestamp.
    Alors max_q devrait être déclaré comme un timestamp.
    Est-il possible d'appliquer dbms_assert.simple_sql_name() une seule fois sur la variable de ma procédure
    En passant par une variable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    is
    l_table2 VARCHAR2(30);
    ...
    begin
    l_table2 := dbms_assert.simple_sql_name(table2);
    ...
    30 c'est suffisant. En passant on préfixe souvent les paramètres par un p_ donc PROCEDURE query_test (p_table1 IN VARCHAR2, p_table2 IN VARCHAR2)

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2011
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2011
    Messages : 60
    Par défaut
    Utiliser USING pour les valeurs des colonnes.
    Peux tu etre plus explicite ?

    SI le prefix p_ est utilisé pour les paramètres de procédure, je suppose que l'on utilise f_ pour les fonctions. Mais à quoi correspond le préfix l_?

Discussions similaires

  1. optimiser le code d'une fonction
    Par yanis97 dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 15/07/2005, 08h41
  2. Optimiser mon code ASP/HTML
    Par ahage4x4 dans le forum ASP
    Réponses: 7
    Dernier message: 30/05/2005, 10h29
  3. optimiser le code
    Par bibi2607 dans le forum ASP
    Réponses: 3
    Dernier message: 03/02/2005, 14h30
  4. syntaxe et optimisation de codes
    Par elitol dans le forum Langage SQL
    Réponses: 18
    Dernier message: 12/08/2004, 11h54
  5. optimisation du code et var globales
    Par tigrou2405 dans le forum ASP
    Réponses: 2
    Dernier message: 23/01/2004, 10h59

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