Oracle PL / SQL - Làm thế nào để tạo một biến mảng đơn giản?


128

Tôi muốn tạo một biến mảng trong bộ nhớ có thể được sử dụng trong mã PL / SQL của tôi. Tôi không thể tìm thấy bất kỳ bộ sưu tập nào trong Oracle PL / SQL sử dụng bộ nhớ thuần, tất cả chúng dường như được liên kết với các bảng. Tôi đang tìm cách làm một cái gì đó như thế này trong PL / SQL (cú pháp C #) của tôi:

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

Chỉnh sửa: Oracle: 9i



1
Tham chiếu "bảng" có xu hướng nôn nao từ cách đặt tên bảng PL / SQL cũ. VARRAYs, Mảng liên kết và các bảng lồng nhau được khai báo là tất cả các kiểu mảng trong bộ nhớ.
Ollie

Câu trả lời:


244

Bạn có thể sử dụng VARRAY cho một mảng có kích thước cố định:

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;

Hoặc BẢNG cho một mảng không giới hạn:

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

Từ "bảng" ở đây không liên quan gì đến các bảng cơ sở dữ liệu, thật khó hiểu. Cả hai phương pháp đều tạo ra các mảng trong bộ nhớ.

Với một trong hai thứ này, bạn cần cả khởi tạo và mở rộng bộ sưu tập trước khi thêm các yếu tố:

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;

Chỉ số đầu tiên là 1 không 0.


75
"khó hiểu" chỉ là về tổng kết Oracle
m.edmondson

Tôi có chèn vào các bảng giống như mảng không? tức làmy_array(0) := 'some string';
Abdul

@TonyAndrews array.extend();EXTEND có thêm một vị trí vào một mảng giới hạn thông thường không? Trong trường hợp đó, nó đã có kích thước động nên không cần một bảng (mảng không giới hạn).
Abdul

2
@Abdul, không, không. Tôi không bao giờ sử dụng VARRAY thông thường nhưng khi kiểm tra đoạn mã trên tôi đã kiểm tra xem điều gì xảy ra nếu bạn cố gắng gia hạn varray(3)4 lần - bạn gặp lỗi "đăng ký vượt quá giới hạn".
Tony Andrew

2
Ước gì tôi có thể bỏ phiếu cho câu trả lời này nhiều lần @TonyAndrews kể từ khi bạn bảo hiểm array.extend(). Mọi nơi tôi nhìn đều không cho thấy điều này và đó là phần quan trọng nhất để có thể thêm nhiều mục (theo cách hiểu của tôi về nó, vẫn còn mới đối với mảng trong SQL).
Jonathan Van Dam

61

Bạn chỉ có thể khai báo DBMS_Query.VARCHAR2_TABLE để giữ một mảng có chiều dài biến trong bộ nhớ được lập chỉ mục bởi 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;

Bạn có thể sử dụng một mảng kết hợp (được gọi là các bảng PL / SQL) vì chúng là một mảng trong bộ nhớ.

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;

Mảng kết hợp có thể chứa bất kỳ cấu tạo của các loại bản ghi.

Hy vọng nó sẽ giúp, Ollie.


17
Điều kiện lặp tăng lên VALUE_ERRORkhi bộ sưu tập trống. Tôi sẽ đề nghị thay vì sử dụng FOR i IN 1 .. employee_array.COUNTtrong trường hợp này
unziberla

Phiên bản của j-chomel ( stackoverflow.com/a/40579334/1915920 ) dựa trên sys.odcivarchar2listbên dưới có lợi thế, bạn cũng có một hàm tạo trong tay, ví dụ: để khởi tạo mặc định param param:sys.odcivarchar2list('val1','val2')
Andreas Dietrich

11

Một giải pháp khác là sử dụng Bộ sưu tập Oracle làm 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

Bạn cũng có thể sử dụng một 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;

Tôi sẽ sử dụng mảng trong bộ nhớ. Nhưng với sự .COUNTcải tiến được đề xuất bởi 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;

Một giải pháp khác là sử dụng Hashmap như @Jchomel đã làm ở đây .

Lưu ý:

Với Oracle 12c, bạn thậm chí có thể truy vấn các mảng ngay bây giờ !


1

Các chương trình mẫu như sau và được cung cấp trên liên kết cũng https://oracle-con accept-learning.blogspot.com/

bảng xin vui lòng hoặc mảng liên quan.

        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; 
        /
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.