Oracle เคอร์เซอร์ PL/SQL: โดยนัย, ชัดเจน, สำหรับลูปพร้อมตัวอย่าง

⚡ สรุปอย่างชาญฉลาด

เคอร์เซอร์ใน Oracle เคอร์เซอร์ใน PL/SQL เป็นตัวชี้ไปยังพื้นที่บริบทที่เก็บแถวที่ส่งคืนโดยคำสั่ง SQL มีสองประเภท ได้แก่ เคอร์เซอร์โดยปริยาย ซึ่งสร้างขึ้นโดยอัตโนมัติสำหรับ DML และเคอร์เซอร์โดยชัดแจ้ง ซึ่งประกาศและควบคุมโดยโปรแกรมเมอร์

  • 📍 พื้นที่บริบท: เคอร์เซอร์ชี้ไปยังพื้นที่บริบทที่เก็บคำสั่ง SQL และชุดข้อมูลที่ใช้งานอยู่ซึ่งส่งคืนโดยคำสั่งนั้น
  • ⚙️ เคอร์เซอร์โดยปริยาย: Oracle เปิดเคอร์เซอร์โดยปริยายโดยอัตโนมัติสำหรับคำสั่ง DML ทุกคำสั่งและคำสั่ง SELECT INTO แบบแถวเดียว
  • เคอร์เซอร์ที่ชัดเจน: โปรแกรมเมอร์ประกาศ เปิด ดึงข้อมูล และปิดเคอร์เซอร์แบบระบุชัดเจน เพื่อควบคุมการทำงานได้อย่างสมบูรณ์
  • 🔎 คุณลักษณะของเคอร์เซอร์: %FOUND, %NOTFOUND, %ISOPEN และ %ROWCOUNT รายงานสถานะของการดำเนินการล่าสุด
  • 🔁 ลูป FOR ของเคอร์เซอร์: ลูป FOR จะเปิด ดึงข้อมูล และปิดเคอร์เซอร์โดยอัตโนมัติ โดยไม่จำเป็นต้องมีขั้นตอนใดๆ ด้วยตนเอง
  • 🤖 ความช่วยเหลือจาก AI: ผู้ช่วย AI เช่น GitHub Copilot จะตรวจจับวงวนของเคอร์เซอร์ในฉบับร่างและแจ้งเตือนเมื่อเคอร์เซอร์ยังไม่ปิด

Oracle เคอร์เซอร์ PL/SQL แบบโดยปริยาย แบบชัดเจน และลูป FOR

เคอร์เซอร์ใน PL/SQL คืออะไร?

เคอร์เซอร์คือตัวชี้ไปยังพื้นที่บริบท Oracle สร้างพื้นที่บริบทสำหรับการประมวลผล SQL ข้อความนี้ประกอบด้วยข้อมูลทั้งหมดเกี่ยวกับข้อความดังกล่าว

PL / SQL ช่วยให้โปรแกรมเมอร์สามารถควบคุมพื้นที่บริบทผ่านเคอร์เซอร์ได้ เคอร์เซอร์จะเก็บแถวที่ได้จากคำสั่ง SQL และชุดของแถวที่เคอร์เซอร์เก็บไว้เรียกว่าชุดที่ใช้งานอยู่ เคอร์เซอร์เหล่านี้ยังสามารถตั้งชื่อได้เพื่อให้สามารถอ้างอิงจากส่วนอื่นของโค้ดได้

เคอร์เซอร์มีสองประเภท:

  • เคอร์เซอร์โดยปริยาย
  • เคอร์เซอร์ที่ชัดเจน

เคอร์เซอร์โดยปริยาย

เมื่อใดก็ตามที่ การดำเนินการ DML เมื่อมีการดำเนินการใดๆ เกิดขึ้นในฐานข้อมูล จะมีการสร้างเคอร์เซอร์โดยปริยายขึ้นมา ซึ่งจะเก็บแถวข้อมูลที่ได้รับผลกระทบจากการดำเนินการนั้นๆ เคอร์เซอร์เหล่านี้ไม่สามารถตั้งชื่อได้ ดังนั้นจึงไม่สามารถควบคุมหรืออ้างอิงจากส่วนอื่นๆ ของโค้ดได้ เราสามารถอ้างอิงถึงเคอร์เซอร์ล่าสุดได้ผ่านทางแอตทริบิวต์ของเคอร์เซอร์เท่านั้น

เคอร์เซอร์ที่ชัดเจน

โปรแกรมเมอร์สามารถสร้างพื้นที่บริบทที่มีชื่อเพื่อดำเนินการคำสั่ง DML และควบคุมการทำงานได้มากขึ้น เคอร์เซอร์ที่ระบุอย่างชัดเจนควรถูกกำหนดไว้ในส่วนการประกาศของคลาส บล็อก PL/SQLและถูกสร้างขึ้นเพื่อใช้กับคำสั่ง SELECT ที่จำเป็นต้องใช้ในโค้ด

ต่อไปนี้คือขั้นตอนในการใช้งานเคอร์เซอร์แบบระบุเจาะจง:

  • การประกาศเคอร์เซอร์: การประกาศเคอร์เซอร์หมายถึงการสร้างพื้นที่บริบทที่มีชื่อสำหรับคำสั่ง SELECT ที่กำหนดไว้ในส่วนของการประกาศ โดยชื่อของพื้นที่บริบทนี้จะเหมือนกับชื่อของเคอร์เซอร์
  • การเปิดเคอร์เซอร์: การเปิดเคอร์เซอร์เป็นการสั่งให้ PL/SQL จัดสรรหน่วยความจำสำหรับเคอร์เซอร์นี้ ทำให้เคอร์เซอร์พร้อมสำหรับการดึงข้อมูล
  • กำลังดึงข้อมูลจากเคอร์เซอร์: ในกระบวนการนี้ คำสั่ง SELECT จะถูกดำเนินการ และแถวที่ดึงมาจะถูกเก็บไว้ในหน่วยความจำที่จัดสรรไว้ ซึ่งตอนนี้เรียกว่าชุดข้อมูลที่ใช้งานอยู่ (active sets) การดึงข้อมูลจากเคอร์เซอร์เป็นกิจกรรมระดับเรคอร์ด ซึ่งหมายความว่าเราสามารถเข้าถึงข้อมูลได้ทีละเรคอร์ด คำสั่ง fetch แต่ละคำสั่งจะดึงชุดข้อมูลที่ใช้งานอยู่หนึ่งชุดและเก็บข้อมูลของเรคอร์ดนั้นๆ คำสั่งนี้เหมือนกับคำสั่ง SELECT ที่ดึงเรคอร์ดและกำหนดให้กับตัวแปรในส่วน INTO แต่จะไม่เกิดข้อผิดพลาดใดๆ ข้อยกเว้น.
  • การปิดเคอร์เซอร์: เมื่อดึงข้อมูลทั้งหมดเสร็จแล้ว เราจำเป็นต้องปิดเคอร์เซอร์เพื่อให้หน่วยความจำที่จัดสรรให้กับพื้นที่บริบทนี้ถูกปล่อยออกมา

วากยสัมพันธ์

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
<cursor_variable declaration>;
BEGIN
OPEN <cursor_name>;
FETCH <cursor_name> INTO <cursor_variable>;
.
.
CLOSE <cursor_name>;
END;

ในไวยากรณ์ข้างต้น ส่วนการประกาศประกอบด้วยการประกาศเคอร์เซอร์และตัวแปรเคอร์เซอร์ซึ่งจะเก็บข้อมูลที่ดึงมา เคอร์เซอร์ถูกสร้างขึ้นสำหรับคำสั่ง SELECT ที่ระบุไว้ในการประกาศเคอร์เซอร์ ในส่วนการดำเนินการ เคอร์เซอร์ที่ประกาศไว้จะถูกเปิด ดึงข้อมูล และปิด

คุณสมบัติเคอร์เซอร์

ทั้งเคอร์เซอร์แบบระบุโดยปริยายและเคอร์เซอร์แบบระบุโดยชัดแจ้งต่างก็มีคุณสมบัติบางอย่างที่สามารถเข้าถึงได้ คุณสมบัติเหล่านี้ให้ข้อมูลเพิ่มเติมเกี่ยวกับการทำงานของเคอร์เซอร์ ด้านล่างนี้คือคุณสมบัติต่างๆ ของเคอร์เซอร์และการใช้งาน

แอตทริบิวต์เคอร์เซอร์ Descriptไอออน
%พบ ฟังก์ชันนี้จะคืนค่าบูลีนเป็น TRUE หากการดึงข้อมูลครั้งล่าสุดดึงข้อมูลได้สำเร็จ มิเช่นนั้นจะคืนค่าเป็น FALSE
%ไม่พบ ทำงานตรงข้ามกับ %FOUND โดยจะคืนค่า TRUE หากการดำเนินการดึงข้อมูลล่าสุดไม่สามารถดึงข้อมูลใดๆ ได้
%เปิด ฟังก์ชันนี้จะคืนค่าบูลีนเป็น TRUE หากเคอร์เซอร์ที่กำหนดเปิดอยู่แล้ว มิเช่นนั้นจะคืนค่าเป็น FALSE
%ROWCOUNT ส่งคืนค่าตัวเลขที่แสดงจำนวนระเบียนที่ได้รับผลกระทบหรือดึงข้อมูลโดยการดำเนินการนั้นจริง

ตัวอย่างการใช้เคอร์เซอร์แบบระบุชัดเจน: ในตัวอย่างนี้ เราจะมาดูวิธีการประกาศ เปิด ดึงข้อมูล และปิดเคอร์เซอร์แบบระบุชัดเจน เราจะดึงรายชื่อพนักงานทั้งหมดจากตาราง emp โดยใช้เคอร์เซอร์ นอกจากนี้ เราจะใช้แอตทริบิวต์ของเคอร์เซอร์เพื่อตั้งค่าลูปให้ดึงข้อมูลทั้งหมดจากเคอร์เซอร์

ภาพหน้าจอด้านล่างแสดงตัวอย่างเคอร์เซอร์แบบชัดเจนและผลลัพธ์ที่ได้ Oracle.

ตัวอย่างการใช้เคอร์เซอร์แบบระบุชัดเจนเพื่อดึงชื่อพนักงานจากตาราง emp ใน Oracle PL / SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
lv_emp_name emp.emp_name%type;
BEGIN
OPEN guru99_det;
LOOP
FETCH guru99_det INTO lv_emp_name;
IF guru99_det%NOTFOUND
THEN
EXIT;
END IF;
Dbms_output.put_line('Employee Fetched:'||lv_emp_name);
END LOOP;
Dbms_output.put_line('Total rows fetched is'||guru99_det%ROWCOUNT);
CLOSE guru99_det;
END;
/

เอาท์พุต

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Total rows fetched is 3

Code คำอธิบาย

  • Code สาย 2: ประกาศเคอร์เซอร์ guru99_det สำหรับคำสั่ง 'SELECT emp_name FROM emp'
  • Code สาย 3: การประกาศตัวแปร lv_emp_name ด้วย %พิมพ์ ยึดโยงกับ emp.emp_name
  • Code สาย 5: กำลังเปิดเคอร์เซอร์ guru99_det
  • Code สาย 6: ตั้งค่าลูปพื้นฐานเพื่อดึงข้อมูลทั้งหมดในตาราง emp
  • Code สาย 7: ดึงข้อมูล guru99_det และกำหนดค่าให้กับ lv_emp_name
  • Code สาย 8: ใช้แอตทริบิวต์ %NOTFOUND ของเคอร์เซอร์เพื่อตรวจสอบว่าดึงข้อมูลทั้งหมดในเคอร์เซอร์มาแล้วหรือไม่ ถ้าดึงมาแล้ว จะส่งค่า TRUE กลับมา และการควบคุมจะออกจากลูป มิเช่นนั้น การควบคุมจะดึงข้อมูลจากเคอร์เซอร์ต่อไปและแสดงผล
  • Code สาย 10: เงื่อนไข EXIT สำหรับคำสั่งลูป
  • Code สาย 12: พิมพ์ชื่อพนักงานที่ดึงมา
  • Code สาย 14: ใช้แอตทริบิวต์เคอร์เซอร์ %ROWCOUNT เพื่อหาจำนวนระเบียนทั้งหมดที่เคอร์เซอร์ดึงมาได้
  • Code สาย 15: หลังจากออกจากลูปแล้ว เคอร์เซอร์จะถูกปิด และหน่วยความจำที่จัดสรรไว้จะถูกปล่อยให้ว่าง

สำหรับคำสั่งลูปเคอร์เซอร์

เคอร์เซอร์ สำหรับห่วง สามารถใช้สำหรับการทำงานกับเคอร์เซอร์ได้ เราสามารถกำหนดชื่อเคอร์เซอร์แทนการกำหนดช่วงในคำสั่งลูป FOR เพื่อให้ลูปทำงานตั้งแต่เรคอร์ดแรกของเคอร์เซอร์ไปจนถึงเรคอร์ดสุดท้ายของเคอร์เซอร์ ตัวแปรเคอร์เซอร์ การเปิดเคอร์เซอร์ การดึงข้อมูล และการปิดเคอร์เซอร์ จะดำเนินการโดยปริยายด้วยลูป FOR

วากยสัมพันธ์

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
BEGIN
FOR I IN <cursor_name>
LOOP
.
.
END LOOP;
END;

ในไวยากรณ์ข้างต้น ส่วนการประกาศประกอบด้วยการประกาศเคอร์เซอร์ เคอร์เซอร์ถูกสร้างขึ้นสำหรับคำสั่ง SELECT ที่ระบุไว้ในการประกาศเคอร์เซอร์ ในส่วนการทำงาน เคอร์เซอร์ที่ประกาศไว้จะถูกตั้งค่าในลูป FOR และตัวแปรลูป 'I' จะทำหน้าที่เป็นตัวแปรเคอร์เซอร์ในกรณีนี้

Oracle ตัวอย่างการใช้เคอร์เซอร์สำหรับลูป: ในตัวอย่างนี้ เราจะแสดงรายชื่อพนักงานทั้งหมดจากตาราง emp โดยใช้ลูป cursor-FOR

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
BEGIN
FOR lv_emp_name IN guru99_det
LOOP
Dbms_output.put_line('Employee Fetched:'||lv_emp_name.emp_name);
END LOOP;
END;
/

เอาท์พุต

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY

Code คำอธิบาย

  • Code สาย 2: ประกาศเคอร์เซอร์ guru99_det สำหรับคำสั่ง 'SELECT emp_name FROM emp'
  • Code สาย 4: สร้างลูป FOR สำหรับเคอร์เซอร์โดยใช้ตัวแปรลูป lv_emp_name
  • Code สาย 6: การพิมพ์ชื่อพนักงานในการวนซ้ำแต่ละครั้ง
  • Code สาย 7: ออกจากลูป (END LOOP)

หมายเหตุ ในลูป FOR ที่ใช้เคอร์เซอร์นั้น ไม่สามารถใช้แอตทริบิวต์ของเคอร์เซอร์ได้ เนื่องจากลูป FOR จะทำการเปิด ดึงข้อมูล และปิดเคอร์เซอร์โดยปริยายอยู่แล้ว

คำถามที่พบบ่อย

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

โดยปกติแล้ว เคอร์เซอร์จะดึงข้อมูลหนึ่งแถวต่อการเรียก FETCH หนึ่งครั้ง ซึ่งทำให้เกิดการสลับบริบทบ่อยครั้ง รวบรวมจำนวนมาก โหลดข้อมูลหลายแถวลงในคอลเลกชันในการดึงข้อมูลครั้งเดียว ช่วยลดภาระการทำงานลงอย่างมากสำหรับชุดผลลัพธ์ขนาดใหญ่

ใช่แล้ว ประกาศเคอร์เซอร์แบบมีพารามิเตอร์ เช่น CURSOR c(dept NUMBER) IS SELECT … จากนั้นส่งค่าที่ OPEN c(10) พารามิเตอร์ช่วยให้คุณสามารถใช้คำจำกัดความของเคอร์เซอร์เดียวกันซ้ำได้ด้วยค่าตัวกรองที่แตกต่างกัน

คำสั่ง FOR UPDATE จะล็อกแถวที่เคอร์เซอร์เลือกไว้ เพื่อไม่ให้ผู้อื่นเปลี่ยนแปลงได้ ส่วนคำสั่ง WHERE CURRENT OF จะทำการอัปเดตหรือลบแถวที่เพิ่งดึงมา โดยไม่ต้องใช้เงื่อนไข WHERE ซ้ำอีก

เคอร์เซอร์ที่เปิดค้างไว้จะสงวนหน่วยความจำไว้และนับรวมอยู่ในขีดจำกัด OPEN_CURSORS การเปิดเคอร์เซอร์ค้างไว้จำนวนมากจะทำให้เกิดข้อผิดพลาด ORA-01000: เกินจำนวนเคอร์เซอร์ที่เปิดค้างไว้สูงสุด ดังนั้นควรปิดเคอร์เซอร์ที่ระบุอย่างชัดเจนทุกครั้งหลังใช้งาน

คำสั่ง FETCH แต่ละคำสั่งจะสลับไปมาระหว่างเอนจิน PL/SQL และ SQL การสลับบริบทแบบนี้เกิดขึ้นนับพันครั้ง ดังนั้นคำสั่ง SQL แบบชุดเดียวหรือคำสั่ง BULK COLLECT จึงมักประมวลผลแถวเดียวกันได้เร็วกว่ามาก

ใช่. นักบิน GitHub ร่างลูป OPEN, FETCH และ CLOSE อย่างชัดเจน หรือลูป FOR ของเคอร์เซอร์จากความคิดเห็น เพิ่มการตรวจสอบการออกจากลูปด้วย %NOTFOUND และแนะนำชื่อแอตทริบิวต์ แต่คุณควรตรวจสอบตรรกะก่อน

ผู้ช่วย AI จะระบุลูปเคอร์เซอร์แบบแถวต่อแถวที่อาจกลายเป็น SQL แบบชุดหรือ BULK COLLECT ตรวจจับเคอร์เซอร์ที่ยังไม่ปิด และอธิบายพฤติกรรมของ %attribute การตรวจสอบด้วยแมชชีนเลิร์นนิงนี้ช่วยปรับปรุงประสิทธิภาพก่อนที่โค้ดจะเข้าสู่ขั้นตอนการผลิต

สรุปโพสต์นี้ด้วย: