Oracle PL / SQL - วิธีสร้างตัวแปรอาร์เรย์อย่างง่าย?


128

ฉันต้องการสร้างตัวแปรอาร์เรย์ในหน่วยความจำที่สามารถใช้ในรหัส PL / SQL ของฉัน ฉันไม่พบคอลเลกชันใด ๆ ใน Oracle PL / SQL ที่ใช้หน่วยความจำแท้ดูเหมือนว่าทุกอย่างจะเชื่อมโยงกับตาราง ฉันกำลังมองหาที่จะทำสิ่งนี้ใน PL / SQL ของฉัน (ไวยากรณ์ C #):

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

แก้ไข: Oracle: 9i



1
การอ้างอิง "table" มีแนวโน้มที่จะเป็น hangover จากการตั้งชื่อตาราง PL / SQL เก่า VARRAYs, อาร์เรย์ที่เกี่ยวข้องและตารางที่ซ้อนกันที่ประกาศเป็นประเภทอาร์เรย์ในหน่วยความจำทั้งหมด
โอลลี่

อ่านลิงค์นี้orafaq.com/wiki/VARRAYและ dba-oracle.com/tips_oracle_varray.htm
zloctb

คำตอบ:


244

คุณสามารถใช้ VARRAY สำหรับอาร์เรย์ขนาดคงที่:

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;

หรือ TABLE สำหรับอาร์เรย์ที่ไม่มีขอบเขต:

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

คำว่า "table" ที่นี่ไม่มีส่วนเกี่ยวข้องกับตารางฐานข้อมูลอย่างสับสน ทั้งสองวิธีสร้างอาร์เรย์ในหน่วยความจำ

ด้วยสิ่งเหล่านี้คุณต้องเริ่มต้นและขยายการรวบรวมก่อนที่จะเพิ่มองค์ประกอบ:

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;

ดัชนีแรกคือ 1 ไม่ใช่ 0


75
"สับสน" เพียงประมาณจำนวน Oracle
m.edmondson

ฉันจะแทรกลงในตารางแบบเดียวกับอาร์เรย์หรือไม่ iemy_array(0) := 'some string';
Abdul

@TonyAndrews array.extend();EXTEND เพิ่มสล็อตในอาร์เรย์ที่มีขอบเขตปกติหรือไม่ ในกรณีนี้มันมีขนาดไดนามิกอยู่แล้วดังนั้นจึงไม่จำเป็นต้องใช้ตาราง (อาร์เรย์ที่ไม่มีขอบเขต)
Abdul

2
@Abdul ไม่เป็นไร ฉันไม่เคยใช้ VARRAY ตามปกติ แต่เมื่อทดสอบรหัสข้างต้นฉันตรวจสอบสิ่งที่เกิดขึ้นหากคุณพยายามที่จะขยายvarray(3)4 ครั้ง - คุณได้รับข้อผิดพลาด "ห้อยเกินขีด จำกัด "
Tony Andrews

2
หวังว่าฉัน coud ขึ้นลงคะแนนคำตอบนี้ @TonyAndrews array.extend()หลายครั้งตั้งแต่คุณครอบคลุม ทุกที่ที่ฉันดูไม่แสดงสิ่งนี้และมันเป็นส่วนที่สำคัญที่สุดในการเพิ่มมากกว่าหนึ่งรายการ (จากความเข้าใจของฉันมันยังใหม่ต่อไปยังอาร์เรย์ใน SQL)
Jonathan Van Dam

61

คุณสามารถประกาศ DBMS_SQL.VARCHAR2_TABLE เพื่อเก็บอาร์เรย์ความยาวของตัวแปรในหน่วยความจำที่จัดทำดัชนีโดย 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;

คุณสามารถใช้อาเรย์แบบเชื่อมโยง (เคยถูกเรียกว่าตาราง PL / SQL) เนื่องจากเป็นอาเรย์ในหน่วยความจำ

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;

อาเรย์แบบเชื่อมโยงสามารถเก็บประเภทบันทึกได้ทุกประเภท

หวังว่ามันจะช่วยโอลลี่


17
เงื่อนไขการวนซ้ำเพิ่มขึ้นVALUE_ERRORเมื่อการรวบรวมว่างเปล่า ฉันอยากจะแนะนำให้ใช้FOR i IN 1 .. employee_array.COUNTในกรณีนี้ค่อนข้าง
unziberla

เวอร์ชั่นของ j-chomel ( stackoverflow.com/a/40579334/1915920 ) ขึ้นอยู่กับsys.odcivarchar2listด้านล่างมีข้อได้เปรียบที่คุณยังมีนวกรรมิกอยู่ในมือเช่นสำหรับการเริ่มต้นของฟังก์ชั่นพารามิเตอร์:sys.odcivarchar2list('val1','val2')
Andreas Dietrich

11

โซลูชันอื่นคือใช้ Oracle Collection เป็น 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

คุณยังสามารถใช้ 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;

ฉันจะใช้อาเรย์ในหน่วยความจำ แต่ด้วยการ.COUNTปรับปรุงที่แนะนำโดย 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;

ทางออกก็จะใช้ HashMap เช่น @Jchomel ได้ที่นี่

หมายเหตุ:

ด้วย Oracle 12c คุณสามารถค้นหาอาร์เรย์ได้ทันที!


1

โปรแกรมตัวอย่างดังต่อไปนี้และมีอยู่ในลิงก์ยังhttps://oracle-concepts-learning.blogspot.com/

ตาราง plsql หรืออาร์เรย์ที่เกี่ยวข้อง

        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; 
        /
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.