155 votes

Oracle PL/SQL - Comment créer une simple variable de type tableau ?

J'aimerais créer une variable de tableau en mémoire qui puisse être utilisée dans mon code PL/SQL. Je ne trouve pas de collections dans Oracle PL/SQL qui utilisent la mémoire pure, elles semblent toutes être associées à des tables. Je cherche à faire quelque chose comme ceci dans mon PL/SQL (syntaxe C#) :

string[] arrayvalues = new string[3] {"Matt", "Joanne", "Robert"};

Edit : Oracle : 9i

2 votes

2 votes

La référence à la "table" a tendance à être une survivance de l'ancienne dénomination des tables PL/SQL. Les tableaux VARRAY, les tableaux associatifs et les tableaux déclarés imbriqués sont tous des types de tableaux en mémoire.

0 votes

283voto

Tony Andrews Points 67363

Vous pouvez utiliser VARRAY pour un tableau de taille fixe :

declare
   type array_t is varray(3) of varchar2(10);
   array array_t := array_t('Matt', 'Joanne', 'Robert');
begin
   for i in 1..array.count loop
       dbms_output.put_line(array(i));
   end loop;
end;

Ou TABLE pour un tableau non borné :

...
   type array_t is table of varchar2(10);
...

Le mot "table" n'a ici rien à voir avec les tables des bases de données, ce qui prête à confusion. Les deux méthodes créent des tableaux en mémoire.

Dans les deux cas, vous devez à la fois initialiser et étendre la collection avant d'ajouter des éléments :

declare
   type array_t is varray(3) of varchar2(10);
   array array_t := array_t(); -- Initialise it
begin
   for i in 1..3 loop
      array.extend(); -- Extend it
      array(i) := 'x';
   end loop;
end;

Le premier indice est 1 et non 0.

90 votes

"confusément" résume à peu près Oracle

0 votes

Est-ce que j'insère dans les tableaux de la même manière que dans les matrices ? my_array(0) := 'some string';

0 votes

@TonyAndrews array.extend(); EXTEND ajoute-t-il un emplacement à un tableau régulier borné ? Dans ce cas, sa taille est déjà dynamique et un tableau (tableau non borné) ne serait pas nécessaire.

70voto

Ollie Points 8526

Vous pourriez simplement déclarer une table DBMS_SQL.VARCHAR2_TABLE pour contenir un tableau de longueur variable en mémoire indexé par un BINARY_INTEGER :

DECLARE
   name_array dbms_sql.varchar2_table;
BEGIN
   name_array(1) := 'Tim';
   name_array(2) := 'Daisy';
   name_array(3) := 'Mike';
   name_array(4) := 'Marsha';
   --
   FOR i IN name_array.FIRST .. name_array.LAST
   LOOP
      -- Do something
   END LOOP;
END;

Vous pouvez utiliser un tableau associatif (autrefois appelé tableau PL/SQL) car il s'agit d'un tableau en mémoire.

DECLARE
   TYPE employee_arraytype IS TABLE OF employee%ROWTYPE
        INDEX BY PLS_INTEGER;
   employee_array employee_arraytype;
BEGIN
   SELECT *
     BULK COLLECT INTO employee_array
     FROM employee
    WHERE department = 10;
   --
   FOR i IN employee_array.FIRST .. employee_array.LAST
   LOOP
      -- Do something
   END LOOP;
END;

Le tableau associatif peut contenir n'importe quelle composition de types d'enregistrements.

J'espère que cela vous aidera, Ollie.

17 votes

La condition d'itération soulève VALUE_ERROR lorsque la collection est vide. Je suggère d'utiliser plutôt FOR i IN 1 .. employee_array.COUNT dans ce cas

0 votes

La version de j-chomel ( stackoverflow.com/a/40579334/1915920 ) sur la base de sys.odcivarchar2list ci-dessous présente l'avantage d'avoir également un constructeur à portée de main, par exemple pour l'initialisation des paramètres de fonction par défaut : sys.odcivarchar2list('val1','val2')

18voto

Jika Points 302

Vous pouvez également utiliser un oracle defined collection

DECLARE 
  arrayvalues sys.odcivarchar2list;
BEGIN
  arrayvalues := sys.odcivarchar2list('Matt','Joanne','Robert');
  FOR x IN ( SELECT m.column_value m_value
               FROM table(arrayvalues) m )
  LOOP
    dbms_output.put_line (x.m_value||' is a good pal');
  END LOOP;
END;

Je voudrais utiliser un tableau en mémoire. Mais avec le .COUNT amélioration suggérée par uziberia :

DECLARE
  TYPE t_people IS TABLE OF varchar2(10) INDEX BY PLS_INTEGER;
  arrayvalues t_people;
BEGIN
  SELECT *
   BULK COLLECT INTO arrayvalues
   FROM (select 'Matt' m_value from dual union all
         select 'Joanne'       from dual union all
         select 'Robert'       from dual
    )
  ;
  --
  FOR i IN 1 .. arrayvalues.COUNT
  LOOP
    dbms_output.put_line(arrayvalues(i)||' is my friend');
  END LOOP;
END;

Une autre solution serait d'utiliser un Hashmap comme @Jchomel a fait ici .

NB :

Avec Oracle 12c, vous pouvez même interroger les tableaux directement maintenant !

13voto

J. Chomel Points 5832

Une autre solution consiste à utiliser une collection Oracle comme hashmap :

declare 
-- create a type for your "Array" - it can be of any kind, record might be useful
  type hash_map is table of varchar2(1000) index by varchar2(30);
  my_hmap hash_map ;
-- i will be your iterator: it must be of the index's type
  i varchar2(30);
begin
  my_hmap('a') := 'apple';
  my_hmap('b') := 'box';
  my_hmap('c') := 'crow';
-- then how you use it:

  dbms_output.put_line (my_hmap('c')) ;

-- or to loop on every element - it's a "collection"
  i := my_hmap.FIRST;

  while (i is not null)  loop     
    dbms_output.put_line(my_hmap(i));      
    i := my_hmap.NEXT(i);
  end loop;

end;

-1voto

sudhirkondle Points 69

Les exemples de programmes sont les suivants et sont également fournis sur le lien https://oracle-concepts-learning.blogspot.com/

table plsql ou tableau associé.

        DECLARE 
            TYPE salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20); 
            salary_list salary; 
            name VARCHAR2(20); 
        BEGIN 
           -- adding elements to the table 
           salary_list('Rajnish') := 62000; salary_list('Minakshi') := 75000; 
           salary_list('Martin') := 100000; salary_list('James') := 78000; 
           -- printing the table name := salary_list.FIRST; WHILE name IS NOT null 
            LOOP 
               dbms_output.put_line ('Salary of ' || name || ' is ' || 
               TO_CHAR(salary_list(name))); 
               name := salary_list.NEXT(name); 
            END LOOP; 
        END; 
        /

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X