Oracle คอลเลกชัน PL/SQL: วาร์เรย์ ซ้อนกัน และจัดทำดัชนีตามตาราง
⚡ สรุปอย่างชาญฉลาด
คอลเลกชันใน PL/SQL คือกลุ่มขององค์ประกอบที่มีชนิดข้อมูลเดียวกันเรียงลำดับ โดยแต่ละองค์ประกอบสามารถเข้าถึงได้ด้วยดัชนี คอลเลกชันมีสามประเภท ได้แก่ Varray, ตารางซ้อน และตารางดัชนี ซึ่งแตกต่างกันในเรื่องขนาดที่คงที่ วิธีการทำงานของดัชนี และความสามารถในการจัดเก็บในฐานข้อมูล

คอลเลกชันคืออะไร?
คอลเลกชันคือกลุ่มขององค์ประกอบที่มีลำดับของชนิดข้อมูลเฉพาะอย่างหนึ่ง อาจเป็นคอลเลกชันของชนิดข้อมูลแบบง่ายหรือชนิดข้อมูลที่ซับซ้อน เช่น ชนิดข้อมูลที่ผู้ใช้กำหนดเองหรือชนิดข้อมูลแบบระเบียน
ในชุดข้อมูล แต่ละองค์ประกอบจะถูกระบุด้วยคำที่เรียกว่า a “ตัวห้อย” แต่ละรายการจะได้รับดัชนีเฉพาะที่ไม่ซ้ำกัน และสามารถจัดการหรือดึงข้อมูลได้โดยอ้างอิงจากดัชนีเฉพาะนั้น
คอลเลกชันมีประโยชน์มากที่สุดเมื่อต้องการประมวลผลหรือจัดการข้อมูลจำนวนมากที่มีประเภทเดียวกัน คอลเลกชันสามารถเติมข้อมูลและจัดการได้ทั้งหมดโดยใช้ตัวเลือก 'BULK' ใน Oracle.
ชุดข้อมูลจะถูกจัดประเภทตามโครงสร้าง ดัชนี และวิธีการจัดเก็บ ดังแสดงด้านล่าง:
- ตารางดัชนี (หรือที่เรียกว่าอาร์เรย์แบบเชื่อมโยง)
- ตารางที่ซ้อนกัน
- วาร์เรย์
ในทุกจุด ข้อมูลในชุดข้อมูลสามารถอ้างอิงได้ด้วยคำสามคำ ได้แก่ ชื่อชุดข้อมูล ดัชนี และชื่อฟิลด์หรือคอลัมน์ เช่น “ ( ) คุณจะได้เรียนรู้เกี่ยวกับหมวดหมู่ของสะสมเหล่านี้ในหัวข้อด้านล่าง
ภาพรวมประเภทของคอลเลกชัน
ประเภทการรวบรวมข้อมูลทั้งสามแบบมีข้อดีข้อเสียแตกต่างกัน ตารางด้านล่างแสดงการเปรียบเทียบประเภทการรวบรวมข้อมูลทั้งสามแบบก่อนที่จะอธิบายรายละเอียดในแต่ละแบบ
| แง่มุม | วาร์เรย์ | ตารางซ้อน | ดัชนีตามตาราง |
|---|---|---|---|
| ขนาด | กำหนดขีดจำกัดสูงสุด | ไม่มีขีด จำกัด | ไม่มีขีด จำกัด |
| ห้อย | เป็นตัวเลข | เป็นตัวเลข | จำนวนเต็มหรือสตริง |
| ความหนาแน่น | หนาแน่นเสมอ | หนาแน่นหรือเบาบาง | มักจะน้อย |
| บันทึกไว้ในฐานข้อมูล | มี (ใบกำกับภาษีเต็มรูปแบบ) | มี (ใบกำกับภาษีเต็มรูปแบบ) | ไม่ |
| จำเป็นต้องเริ่มต้นใช้งาน | มี (ใบกำกับภาษีเต็มรูปแบบ) | มี (ใบกำกับภาษีเต็มรูปแบบ) | ไม่ |
วาร์เรย์
Varray คือคอลเลกชันที่มีขนาดคงที่และไม่สามารถเปลี่ยนแปลงได้ ดัชนีของ Varray เป็นค่าตัวเลข คุณสมบัติของ Varray มีดังนี้:
- ขนาดสูงสุดถูกกำหนดไว้แล้ว
- เรียงลำดับตามจำนวนสมาชิก โดยเริ่มจากเลขห้อย '1'
- ประเภทคอลเลกชันนี้มีความหนาแน่นสูงเสมอ เราไม่สามารถลบองค์ประกอบแต่ละรายการในอาร์เรย์ได้ สามารถลบ Varray ทั้งหมดหรือตัดส่วนท้ายออกได้
- เนื่องจากมีความหนาแน่นสูง จึงมีความยืดหยุ่นน้อยมาก
- วิธีนี้จะเหมาะสมกว่าเมื่อทราบขนาดของอาร์เรย์และมีการดำเนินการที่คล้ายคลึงกันกับทุกองค์ประกอบ
- ดัชนีและจำนวนของชุดข้อมูลจะคงที่เสมอ
- ต้องทำการกำหนดค่าเริ่มต้นก่อนใช้งาน การดำเนินการใดๆ ยกเว้น EXISTS บนคอลเลกชันที่ยังไม่ได้กำหนดค่าเริ่มต้น จะทำให้เกิดข้อผิดพลาด
- สามารถสร้างเป็นอ็อบเจ็กต์ในฐานข้อมูลที่มองเห็นได้ทั่วทั้งฐานข้อมูล หรือสร้างไว้ภายในโปรแกรมย่อยเพื่อใช้งานเฉพาะในโปรแกรมย่อยนั้นก็ได้
ภาพด้านล่างนี้อธิบายการจัดสรรหน่วยความจำของ Varray (แบบหนาแน่น)
| ห้อย | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| ความคุ้มค่า | xyz | ดฟฟ | สเด | Cxs | วบีซี | นู | Qwe |
ไวยากรณ์สำหรับ VARRAY:
TYPE <type_name> IS VARRAY (<SIZE>) OF <DATA_TYPE>;
- ในไวยากรณ์ข้างต้น type_name ถูกประกาศเป็น VARRAY ของชนิด 'DATA_TYPE' สำหรับขนาดที่กำหนดไว้ ชนิดข้อมูลอาจเป็นแบบง่ายหรือแบบซับซ้อนก็ได้
ตารางที่ซ้อนกัน
ตารางซ้อน (Nested Table) คือชุดข้อมูลที่ขนาดของอาร์เรย์ไม่คงที่ มีชนิดข้อมูลเป็นตัวเลข (Numeric Subscript Type) ข้อมูลเพิ่มเติมเกี่ยวกับชนิดข้อมูลตารางซ้อน:
- ตารางซ้อนไม่มีข้อจำกัดขนาดสูงสุด
- เนื่องจากขีดจำกัดสูงสุดไม่คงที่ จึงจำเป็นต้องขยายหน่วยความจำทุกครั้งก่อนใช้งาน โดยใช้คำสั่ง 'EXTEND'
- เรียงลำดับตามจำนวนสมาชิก โดยเริ่มจากเลขห้อย '1'
- ประเภทคอลเลกชันนี้สามารถเป็นได้ทั้งสองแบบ หนาแน่นและเบาบางเราสามารถสร้างมันให้มีความหนาแน่นสูง และยังสามารถลบองค์ประกอบแต่ละส่วนแบบสุ่ม ซึ่งจะทำให้มันมีความหนาแน่นต่ำลงได้
- ทำให้มีความยืดหยุ่นมากขึ้นในการลบองค์ประกอบในอาร์เรย์
- ข้อมูลจะถูกจัดเก็บไว้ในตารางฐานข้อมูลที่ระบบสร้างขึ้น และสามารถใช้ในคำสั่งเลือกข้อมูลเพื่อดึงค่าได้
- ตัวเลขดัชนีและจำนวนนับอาจแตกต่างกันได้
- ต้องทำการกำหนดค่าเริ่มต้นก่อนใช้งาน การดำเนินการใดๆ ยกเว้น EXISTS บนคอลเลกชันที่ยังไม่ได้กำหนดค่าเริ่มต้น จะทำให้เกิดข้อผิดพลาด
- สามารถสร้างเป็นอ็อบเจ็กต์ในฐานข้อมูลที่มองเห็นได้ทั่วทั้งฐานข้อมูล หรือสร้างไว้ภายในโปรแกรมย่อยเพื่อใช้งานเฉพาะในโปรแกรมย่อยนั้นก็ได้
ภาพด้านล่างอธิบายการจัดสรรหน่วยความจำของตารางซ้อน (แบบหนาแน่นและแบบเบาบาง) พื้นที่ว่างสำหรับองค์ประกอบแสดงถึงองค์ประกอบแบบเบาบาง
| ห้อย | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| ค่า (หนาแน่น) | xyz | ดฟฟ | สเด | Cxs | วบีซี | นู | Qwe |
| ค่า (กระจัดกระจาย) | Qwe | asd | อัฟกานิสถาน | asd | wer |
ไวยากรณ์สำหรับตารางที่ซ้อนกัน:
TYPE <type_name> IS TABLE OF <DATA_TYPE>;
- ในไวยากรณ์ข้างต้น type_name ถูกประกาศเป็นคอลเลกชันตารางซ้อนของประเภท 'DATA_TYPE' โดยชนิดข้อมูลอาจเป็นแบบง่ายหรือแบบซับซ้อนก็ได้
ดัชนีตามตาราง
ตารางดัชนี (Index-by Table) คือชุดข้อมูลที่ขนาดของอาร์เรย์ไม่คงที่ แตกต่างจากชุดข้อมูลประเภทอื่น ๆ ตรงที่ดัชนีของตารางดัชนีสามารถกำหนดได้โดยผู้ใช้ คุณลักษณะของตารางดัชนีมีดังนี้:
- ดัชนีสามารถเป็นจำนวนเต็มหรือสตริงก็ได้ ควรระบุประเภทของดัชนีเมื่อสร้างคอลเลกชัน
- คอลเลกชันเหล่านี้ไม่ได้จัดเก็บตามลำดับ
- พวกมันจะเบาบางในธรรมชาติอยู่เสมอ
- ขนาดอาร์เรย์ไม่คงที่
- ไม่สามารถจัดเก็บไว้ในคอลัมน์ของฐานข้อมูลได้ เนื่องจากถูกสร้างและใช้งานภายในเซสชันนั้นๆ เท่านั้น
- วิธีนี้ช่วยให้มีความยืดหยุ่นมากขึ้นในการรักษามูลค่าดัชนี
- ตัวเลขดัชนีอาจเป็นลำดับติดลบได้
- วิธีการนี้เหมาะสมกว่าสำหรับการใช้งานกับชุดข้อมูลที่มีค่าค่อนข้างน้อยภายในโปรแกรมย่อยเดียวกัน
- ไม่จำเป็นต้องกำหนดค่าเริ่มต้นก่อนใช้งาน
- ไม่สามารถสร้างเป็นอ็อบเจ็กต์ในฐานข้อมูลได้ แต่จะสร้างขึ้นภายในโปรแกรมย่อยเท่านั้น
- ไม่สามารถใช้ BULK COLLECT กับประเภทการรวบรวมข้อมูลนี้ได้ เนื่องจากต้องระบุตัวเลขดัชนีสำหรับแต่ละรายการอย่างชัดเจน
ภาพด้านล่างอธิบายการจัดสรรหน่วยความจำของตารางดัชนี (แบบสปาร์ส) พื้นที่ว่างสำหรับองค์ประกอบแสดงถึงองค์ประกอบแบบสปาร์ส
| ตัวห้อย (varchar) | FIRST | นาปรัง | ที่สาม | FOURTH | ที่ห้า | หก | เจ็ด |
| ค่า (กระจัดกระจาย) | Qwe | asd | อัฟกานิสถาน | asd | wer |
ไวยากรณ์สำหรับการสร้างดัชนีตามตาราง:
TYPE <type_name> IS TABLE OF <DATA_TYPE> INDEX BY VARCHAR2 (10);
- ในไวยากรณ์ข้างต้น type_name ถูกประกาศเป็นคอลเลกชันตารางแบบดัชนีของชนิด 'DATA_TYPE' ตัวแปรดัชนีถูกกำหนดให้เป็นชนิด VARCHAR2 โดยมีขนาดสูงสุด 10
คอนสตรัคเตอร์และแนวคิดการเริ่มต้นในคอลเลกชัน
คอนสตรัคเตอร์คือฟังก์ชันในตัวที่จัดเตรียมโดย Oracle เมธอดเหล่านี้จะมีชื่อเดียวกันกับอ็อบเจ็กต์หรือคอลเลกชัน และจะถูกเรียกใช้งานก่อนเป็นอันดับแรกทุกครั้งที่มีการอ้างอิงถึงอ็อบเจ็กต์หรือคอลเลกชันเป็นครั้งแรกในเซสชัน รายละเอียดสำคัญของคอนสตรัคเตอร์ในบริบทของคอลเลกชันมีดังนี้:
- สำหรับคอลเลกชัน จำเป็นต้องเรียกใช้คอนสตรัคเตอร์เหล่านี้อย่างชัดเจนเพื่อเริ่มต้นคอลเลกชัน
- ทั้ง Varray และตารางซ้อนต้องได้รับการเริ่มต้นใช้งานผ่านตัวสร้างเหล่านี้ก่อนที่จะนำไปอ้างอิงในโปรแกรม
- คอนสตรัคเตอร์จะขยายการจัดสรรหน่วยความจำสำหรับคอลเลกชันโดยปริยาย (ยกเว้น Varray) ดังนั้นจึงสามารถกำหนดค่าตัวแปรให้กับคอลเลกชันได้ด้วย
- การกำหนดค่าผ่านคอนสตรัคเตอร์จะไม่ทำให้คอลเลกชันนั้นกระจัดกระจายแต่อย่างใด
วิธีการเก็บรวบรวม
Oracle มีฟังก์ชันมากมายที่ใช้ในการจัดการและทำงานกับคอลเลกชัน ฟังก์ชันเหล่านี้จะกำหนดและแก้ไขคุณลักษณะต่างๆ ของคอลเลกชัน ตารางด้านล่างแสดงฟังก์ชันต่างๆ และคำอธิบายของแต่ละฟังก์ชัน
| วิธี | Descriptไอออน | วากยสัมพันธ์ |
|---|---|---|
| มีอยู่ (n) | ส่งคืนค่าบูลีน โดยจะคืนค่า TRUE หากองค์ประกอบที่ n มีอยู่ และคืนค่า FALSE หากไม่พบ สามารถใช้ EXISTS ได้เฉพาะกับคอลเลกชันที่ยังไม่ได้กำหนดค่าเริ่มต้นเท่านั้น | .มีอยู่(element_position) |
| COUNT | แสดงจำนวนรวมขององค์ประกอบที่มีอยู่ในคอลเลกชัน | .นับ |
| LIMIT | ส่งคืนขนาดสูงสุดของคอลเลกชัน สำหรับ Varray จะส่งคืนขนาดคงที่ สำหรับตารางแบบซ้อนและตารางแบบใช้ดัชนี จะส่งคืนค่า NULL | .จำกัด |
| FIRST | ส่งคืนค่าของดัชนีแรกของคอลเลกชัน | .อันดับแรก |
| LAST | ส่งคืนค่าดัชนีสุดท้ายของคอลเลกชัน | .ล่าสุด |
| ก่อน (n) | ส่งคืนดัชนีก่อนหน้าขององค์ประกอบที่ n หากไม่มี จะส่งคืนค่า NULL | .ก่อน(n) |
| ถัดไป (n) | ส่งคืนดัชนีถัดไปขององค์ประกอบที่ n หากไม่มี จะส่งคืนค่า NULL | .ถัดไป(n) |
| ขยาย | เพิ่มองค์ประกอบหนึ่งรายการต่อท้ายชุดข้อมูล | .ขยาย |
| ขยาย (n) | เพิ่มองค์ประกอบ n ตัวที่ส่วนท้ายของคอลเลกชัน | .ขยาย(n) |
| ขยาย (n,i) | เพิ่มสำเนา n ชุดขององค์ประกอบที่ i ต่อท้ายชุดข้อมูล | .ขยาย(n,i) |
| TRIM | ลบองค์ประกอบหนึ่งรายการออกจากส่วนท้ายของชุดข้อมูล | .ทริม |
| ตัดแต่ง (n) | ลบองค์ประกอบจำนวน n รายการออกจากส่วนท้ายของคอลเลกชัน | .ทริม (n) |
| ลบ | ลบองค์ประกอบทั้งหมดออกจากคอลเลกชัน ทำให้คอลเลกชันว่างเปล่า | .ลบ |
| ลบ (n) | ลบองค์ประกอบที่ n หากองค์ประกอบที่ n เป็น NULL จะไม่ทำอะไรเลย | .ลบ(n) |
| ลบ (นาที,n) | ลบองค์ประกอบในช่วงลำดับที่ m ถึง n ในคอลเลกชัน | .DELETE(ม,n) |
ตัวอย่างที่ 1: ประเภทเรคอร์ดในระดับซับโปรแกรม
ในตัวอย่างนี้ เราจะเห็นวิธีการเติมข้อมูลลงในคอลเลกชันโดยใช้ 'รวบรวมจำนวนมากและวิธีการอ้างอิงข้อมูลที่รวบรวมไว้
DECLARE TYPE emp_det IS RECORD ( EMP_NO NUMBER, EMP_NAME VARCHAR2(150), MANAGER NUMBER, SALARY NUMBER ); TYPE emp_det_tbl IS TABLE OF emp_det; guru99_emp_rec emp_det_tbl:= emp_det_tbl(); BEGIN INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1000,'AAA',25000,1000); INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1001,'XXX',10000,1000); INSERT INTO emp (emp_no, emp_name, salary, manager) VALUES (1002,'YYY',15000,1000); INSERT INTO emp (emp_no,emp_name,salary, manager) VALUES (1003,'ZZZ',7500,1000); COMMIT; SELECT emp_no,emp_name,manager,salary BULK COLLECT INTO guru99_emp_rec FROM emp; dbms_output.put_line ('Employee Detail'); FOR i IN guru99_emp_rec.FIRST..guru99_emp_rec.LAST LOOP dbms_output.put_line ('Employee Number: '||guru99_emp_rec(i).emp_no); dbms_output.put_line ('Employee Name: '||guru99_emp_rec(i).emp_name); dbms_output.put_line ('Employee Salary:'|| guru99_emp_rec(i).salary); dbms_output.put_line('Employee Manager Number:'||guru99_emp_rec(i).manager); dbms_output.put_line('--------------------------------'); END LOOP; END; /
Code คำอธิบาย
- Code บรรทัดที่ 2-8: ประเภทบันทึก ตาราง 'emp_det' ถูกประกาศโดยมีคอลัมน์ emp_no, emp_name, manager และ salary ซึ่งมีชนิดข้อมูลเป็น NUMBER, VARCHAR2, NUMBER และ NUMBER ตามลำดับ
- Code สาย 9: กำลังสร้างคอลเลกชัน 'emp_det_tbl' ที่มีประเภทเรคอร์ดเป็นองค์ประกอบ 'emp_det'
- Code สาย 10: ประกาศตัวแปร 'guru99_emp_rec' เป็นชนิด 'emp_det_tbl' และกำหนดค่าเริ่มต้นให้ตัวแปรนั้นด้วยคอนสตรัคเตอร์ที่เป็นค่าว่าง
- Code บรรทัดที่ 12-15: การแทรกข้อมูลตัวอย่างลงในตาราง 'emp'
- Code สาย 16: ยืนยันธุรกรรมการแทรก
- Code สาย 17: ดึงข้อมูลจากตาราง 'emp' และเติมข้อมูลลงในตัวแปรคอลเลกชันแบบกลุ่มโดยใช้คำสั่ง “BULK COLLECT” ขณะนี้ตัวแปร 'guru99_emp_rec' มีข้อมูลทั้งหมดที่มีอยู่ในตาราง 'emp' แล้ว
- Code บรรทัดที่ 19-26: ตั้งค่าลูป 'FOR' เพื่อพิมพ์ข้อมูลทั้งหมดในคอลเลกชันทีละรายการ โดยใช้เมธอด FIRST และ LAST เป็นขีดจำกัดล่างและบนของคอลเลกชัน ห่วง.
Output: เมื่อรันโค้ดข้างต้น คุณจะได้ผลลัพธ์ดังต่อไปนี้
Employee Detail Employee Number: 1000 Employee Name: AAA Employee Salary: 25000 Employee Manager Number: 1000 ---------------------------------------------- Employee Number: 1001 Employee Name: XXX Employee Salary: 10000 Employee Manager Number: 1000 ---------------------------------------------- Employee Number: 1002 Employee Name: YYY Employee Salary: 15000 Employee Manager Number: 1000 ---------------------------------------------- Employee Number: 1003 Employee Name: ZZZ Employee Salary: 7500 Employee Manager Number: 1000 ----------------------------------------------

