web-dev-qa-db-fra.com

table temporaire à l'intérieur de l'oracle de la procédure

Je suis dans une situation en ce moment. Je migre plusieurs procédures de Mysql 5.0 vers Oracle 11g. Les procédures Mysql me permettent de:
1. Créer des tables temporaires
2. Insérer des données dans des tables temporaires/Interroger ces tables/Faire certains processus
. Supprimer les tables temporaires

J'ai cherché et j'ai découvert que je ne pouvais pas créer d'instructions DDL dans les procédures sans l'instruction EXECUTE IMMEDIATE. J'ai essayé de créer la table temporaire avec cette instruction, et d'y insérer immédiatement quelques valeurs mais cela ne fonctionne pas car la table n'existe pas déjà. J'ai essayé de créer une fonction qui crée une table temporaire, puis de l'appeler à partir de la procédure mais la même chose se produit.

J'ai besoin de réaliser les mêmes étapes que je fais avec MySQL. Cette situation se produit très souvent (il y a tellement de procédures avec ce genre de "problème") et elles sont assez importantes.

Quelles options ai-je, que recommandez-vous?

6
Alejandro Bastidas

Cela dépend de la raison pour laquelle vous créez les tables temporaires dans MySQL.

Souvent, les personnes qui créent des tables temporaires dans d'autres bases de données le font afin de contourner les limitations qui n'existent pas dans Oracle où les lecteurs ne bloquent pas les écrivains et les écrivains ne bloquent pas les lecteurs. Dans d'autres bases de données, vous copiez généralement des données d'une table permanente vers une table temporaire afin que votre processus ne bloque pas un autre processus qui a besoin des mêmes données. Étant donné qu'Oracle offre une cohérence de lecture multi-version, cependant, cela n'est pas nécessaire (ou avantageux) dans Oracle - votre processus peut traiter les données se trouvant dans les vraies tables sans se soucier du fait qu'il va bloquer quelqu'un d'autre. Si tel est le cas, la réponse appropriée consiste simplement à supprimer les tables temporaires et à traiter les données des tables permanentes.

En supposant que vous ayez vraiment besoin d'une copie temporaire des données, vous pouvez créer des tables temporaires globales. Vous devez créer ces tables en dehors de votre code comme une table permanente et les utiliser comme une table permanente à l'intérieur de votre code. La table temporaire globale garantit que chaque session ne peut voir que les données insérées par cette session. La seule différence est que vous ne supprimez pas et ne recréez pas la structure du tableau à l'intérieur de votre procédure.

Une autre alternative serait d'extraire les données dans une collection PL/SQL avec laquelle vous travaillez plutôt que d'utiliser une table temporaire. Les collections PL/SQL sont stockées dans le PGA du serveur (l'une des structures de mémoire d'Oracle), vous devez donc généralement limiter la taille de la collection, en particulier s'il y a beaucoup de données à traiter ou s'il peut y avoir de nombreuses sessions traitant des données simultanément. Vous pouvez faire quelque chose comme

DECLARE
  TYPE emp_tbl IS TABLE OF emp%rowtype;
  l_emps emp_tbl;

  CURSOR emp_cur 
      IS SELECT *
           FROM emp;
BEGIN
  OPEN emp_cur;
  LOOP
    -- Fetch 10 rows at a time from the cursor into the collection.
    -- You'd realistically want a larger limit, something between 100 and 1000 generally
    FETCH emp_cur 
     BULK COLLECT INTO l_emps
    LIMIT 10;

    EXIT WHEN l_emps.COUNT = 0;

    -- An example of manipulating the collection in memory
    FOR i IN 1 .. l_emps.COUNT
    LOOP
      l_emps(i).sal := l_emps(i).sal * 2;
    END LOOP;

    -- And an example of using the collection to update a table
    FORALL i IN 1 .. l_emps.COUNT
      UPDATE emp
         SET sal = l_emps(i).sal
       WHERE empno = l_emps(i).empno;
  END LOOP;
END;

Bien sûr, dans l'exemple ci-dessus, il serait beaucoup plus simple (et plus efficace) d'émettre simplement une instruction UPDATE qui doublerait le salaire de chaque employé.

8
Justin Cave