Oracle PL / SQL - Bagaimana cara membuat variabel array sederhana?


128

Saya ingin membuat variabel array dalam memori yang dapat digunakan dalam kode PL / SQL saya. Saya tidak dapat menemukan koleksi di Oracle PL / SQL yang menggunakan memori murni, semuanya tampaknya terkait dengan tabel. Saya ingin melakukan sesuatu seperti ini di PL / SQL (sintaks C #) saya:

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

Sunting: Oracle: 9i



1
Referensi "tabel" cenderung hangover dari penamaan tabel PL / SQL lama. VARRAY, Array Asosiatif, dan tabel bertingkat yang diumumkan adalah semua jenis array dalam memori.
Ollie

Jawaban:


244

Anda dapat menggunakan VARRAY untuk array ukuran tetap:

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;

Atau TABEL untuk larik tak terbatas:

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

Kata "tabel" di sini tidak ada hubungannya dengan tabel database, membingungkan. Kedua metode membuat array dalam memori.

Dengan salah satu dari ini, Anda perlu menginisialisasi dan memperluas koleksi sebelum menambahkan elemen:

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;

Indeks pertama adalah 1 bukan 0.


75
"membingungkan" hanya meringkas Oracle
m.edmondson

Apakah saya memasukkan ke dalam tabel dengan cara yang sama seperti array? yaitumy_array(0) := 'some string';
Abdul

@TonyAndrews array.extend();apakah EXTEND menambahkan slot ke array terikat reguler? Dalam hal ini, ukurannya sudah dinamis sehingga sebuah tabel (array tidak terikat) tidak diperlukan.
Abdul

2
@ Abdul, tidak, tidak. Saya tidak pernah menggunakan VARRAYs secara normal tetapi ketika menguji kode di atas saya memeriksa apa yang terjadi jika Anda mencoba untuk memperpanjang varray(3)4 kali - Anda mendapatkan kesalahan "subskrip di luar batas".
Tony Andrews

2
Seandainya saya dapat memilih jawaban ini beberapa kali @TonyAndrews sejak Anda meliput array.extend(). Setiap tempat saya melihat tidak menunjukkan ini dan itu adalah bagian paling penting untuk dapat menambahkan lebih dari satu item (dari pemahaman saya tentang hal itu, masih baru untuk array dalam SQL).
Jonathan Van Dam

61

Anda bisa mendeklarasikan DBMS_SQL.VARCHAR2_TABLE untuk menahan array panjang variabel di dalam memori yang diindeks oleh 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;

Anda bisa menggunakan array asosiatif (dulu disebut tabel PL / SQL) karena array dalam memori.

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;

Array asosiatif dapat menampung jenis rekaman apa pun.

Semoga ini bisa membantu, Ollie.


17
Kondisi iterasi meningkat VALUE_ERRORketika koleksi kosong. Saya akan menyarankan untuk menggunakan FOR i IN 1 .. employee_array.COUNTdalam kasus ini
unziberla

Versi j-chomel ( stackoverflow.com/a/40579334/1915920 ) berdasarkan di sys.odcivarchar2listbawah ini memiliki keuntungan, bahwa Anda juga memiliki konstruktor, misalnya untuk inisialisasi fungsi param standar:sys.odcivarchar2list('val1','val2')
Andreas Dietrich

11

Solusi lain adalah dengan menggunakan Oracle Collection sebagai 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;

11

Anda juga dapat menggunakan 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;

Saya akan menggunakan array dalam memori. Tetapi dengan .COUNTperbaikan yang disarankan oleh 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;

Solusi lain adalah dengan menggunakan Hashmap seperti @Jchomel lakukan di sini .

NB:

Dengan Oracle 12c Anda bahkan dapat meminta array langsung sekarang !


1

Contoh program sebagai berikut dan disediakan di tautan juga https://oracle-concepts-learning.blogspot.com/

tabel plsql atau larik terkait.

        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; 
        /
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.