Oracle การสอน PL/SQL Dynamic SQL: ดำเนินการทันที & DBMS_SQL
ไดนามิก SQL คืออะไร?
พลวัต SQL เป็นวิธีการเขียนโปรแกรมสำหรับการสร้างและรันคำสั่ง ณ รันไทม์ ส่วนใหญ่จะใช้เพื่อเขียนโปรแกรมอเนกประสงค์และยืดหยุ่น โดยที่คำสั่ง SQL จะถูกสร้างขึ้นและดำเนินการ ณ รันไทม์ตามความต้องการ
วิธีเขียนไดนามิก SQL
PL/SQL มีสองวิธีในการเขียน SQL แบบไดนามิก
- NDS – Native Dynamic SQL
- DBMS_SQL
NDS (Native Dynamic SQL) – ดำเนินการทันที
Native Dynamic SQL เป็นวิธีการเขียน SQL แบบไดนามิกที่ง่ายกว่า โดยใช้คำสั่ง 'EXECUTE IMMEDIATE' เพื่อสร้างและดำเนินการ SQL ในขณะรันไทม์ แต่ในการใช้วิธีนี้ จำเป็นต้องทราบประเภทข้อมูลและจำนวนตัวแปรที่จะใช้ในขณะรันไทม์เสียก่อน นอกจากนี้ยังให้ประสิทธิภาพที่ดีกว่าและความซับซ้อนน้อยกว่าเมื่อเปรียบเทียบกับ DBMS_SQL
วากยสัมพันธ์
EXECUTE IMMEDIATE(<SQL>) [INTO<variable>] [USING <bind_variable_value>]
- ไวยากรณ์ข้างต้นแสดงคำสั่ง EXECUTE IMMEDIATE
- Clause INTO เป็นทางเลือก และใช้เฉพาะในกรณีที่ SQL ไดนามิกมีคำสั่ง select ที่ดึงค่าออกมาเท่านั้น ประเภทของตัวแปรควรตรงกับประเภทตัวแปรของคำสั่ง select
- ส่วนคำสั่ง USING เป็นทางเลือก และใช้เฉพาะในกรณีที่ SQL ไดนามิกมีตัวแปรการโยงใดๆ
1 ตัวอย่าง: ในตัวอย่างนี้ เราจะดึงข้อมูลจากตาราง emp สำหรับ emp_no '1001' โดยใช้คำสั่ง NDS
DECLARE lv_sql VARCHAR2(500); lv_emp_name VARCHAR2(50): ln_emp_no NUMBER; ln_salary NUMBER; ln_manager NUMBER; BEGIN ly_sql:=;SELECT emp_name,emp_no,salary,manager FROM emp WHERE emp_no=:empmo:; EXECUTE IMMEDIATE lv_sql INTO lv_emp_name,ln_emp_no:ln_salary,ln_manager USING 1001; Dbms_output.put_line('Employee Name:‘||lv_emp_name); Dbms_output.put_line('Employee Number:‘||ln_emp_no); Dbms_output.put_line(‘Salary:'||ln_salaiy); Dbms_output.put_line('Manager ID:‘||ln_manager); END; /
เอาท์พุต
Employee Name : XXX Employee Number: 1001 Salary: 15000 Manager ED: 1000
คำอธิบายรหัส:
- รหัสบรรทัด 2-6: การประกาศตัวแปร
- รหัสบรรทัดที่ 8: การเฟรม SQL ณ รันไทม์ SQL มีตัวแปรการเชื่อมโยงโดยที่เงื่อนไข ':empno'
- รหัสบรรทัดที่ 9: การดำเนินการข้อความ SQL ที่มีเฟรม (ซึ่งทำในโค้ดบรรทัด 8) โดยใช้คำสั่ง NDS 'EXECUTE IMMEDIATE'
- ตัวแปรในส่วนคำสั่ง 'INTO' (lv_emp_name, ln_emp_no, ln_salary, ln_manager) ใช้เพื่อเก็บค่าที่ดึงมาจากแบบสอบถาม SQL (emp_name, emp_no, เงินเดือน, ผู้จัดการ)
- ส่วนคำสั่ง 'USING' ให้ค่าแก่ตัวแปรการผูกในการสืบค้น SQL (:emp_no)
- รหัสบรรทัด 10-13: การแสดงค่าที่ดึงมา
DBMS_SQL สำหรับไดนามิก SQL
PL/SQL มีแพ็คเกจ DBMS_SQL ที่ช่วยให้คุณทำงานกับ SQL แบบไดนามิกได้ กระบวนการสร้างและดำเนินการ SQL แบบไดนามิกประกอบด้วยกระบวนการต่อไปนี้
- เปิดเคอร์เซอร์: Dynamic SQL จะดำเนินการในลักษณะเดียวกับ a เคอร์เซอร์- ดังนั้นเพื่อที่จะรันคำสั่ง SQL เราจะต้องเปิดเคอร์เซอร์
- แยกวิเคราะห์ SQL: ขั้นตอนต่อไปคือการแยกวิเคราะห์ SQL แบบไดนามิก กระบวนการนี้จะตรวจสอบไวยากรณ์และทำให้แบบสอบถามพร้อมที่จะดำเนินการ
- ผูกค่าตัวแปร: ขั้นตอนต่อไปคือการกำหนดค่าสำหรับตัวแปรการผูกถ้ามี
- กำหนดคอลัมน์: ขั้นตอนต่อไปคือการกำหนดคอลัมน์โดยใช้ตำแหน่งที่สัมพันธ์กันในคำสั่ง select
- ดำเนินการ: ขั้นตอนต่อไปคือการดำเนินการแบบสอบถามแบบแยกวิเคราะห์
- ดึงค่า: ขั้นตอนต่อไปคือการดึงค่าที่ดำเนินการ
- ปิดเคอร์เซอร์: เมื่อดึงผลลัพธ์แล้ว ควรปิดเคอร์เซอร์
1 ตัวอย่าง: ในตัวอย่างนี้ เราจะดึงข้อมูลจากตาราง emp สำหรับ emp_no '1001' โดยใช้คำสั่ง DBMS_SQL
DECLARE lv_sql VARCHAR2(500); lv_emp_name VARCHAR2(50); ln_emp_no NUMBER; ln_salary NUMBER; ln_manager NUMBER; ln_cursor_id NUMBER; ln_rows_processed; BEGIN lv_sql:=‘SELECT emp_name,emp_no,salary,manager FROM emp WHERE emp_no=:empmo’; in_cursor_id:=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(ln_cursor_id,lv_sql,DBMS_SQL.NATIVE); DBMS_SQL.BIXD_VARLABLE(ln_cursor_id,:‘empno‘,1001); DBMS_SQL.DEFINE_COLUMN(ln_cursor_ici,1,ln_emp_name); DBMS_SQL.DEFINE_COLUMN(ln_cursor_id,2,ln_emp_no); DBMS_SQL .DEFINE_COLUMN(ln_cursor_id,3,ln_salary); DBMS_SQL .DEFINE_COLUMN(ln_cursor_id,4,ln_manager); ln_rows__processed:=DBMS_SQL.EXECUTE(ln_cursor_id);
LOOP IF DBMS_SQL.FETCH_ROWS(ln_cursor_id)=0 THEN EXIT; ELSE DBMS_SQL.COLUMN_VALUE(ln_cursor_id,1,lv_emp_name); DBMS_SQL.COLUMN_VALUE(ln_cursor_id,2,ln_emp_no); DBMS_SQL.COLUMN_VALUE(ln_cursor_id,3,In_salary); DBMS_SQL.COLUMN_VALUE(ln_cursor_id,4,In_manager); Dbms_output.put_line('Employee Name:‘||lv_emp_name); Dbms_output.put_line('Employee Number:l‘||ln_emp_no); Dbms_output.put_line(‘Salary:‘||ln_salary); Dbms_output.put_line('Manager ID :‘| ln_manager); END IF; END LOOP; DBMS_SQL.CLOSE_ClIRSOR(ln_cursor_id); END: /
เอาท์พุต
Employee Name:XXX Employee Number:1001 Salary:15000 Manager ID:1000
คำอธิบายรหัส:
- รหัสบรรทัด 1-9: การประกาศตัวแปร
- รหัสบรรทัดที่ 10: กรอบคำสั่ง SQL
- รหัสบรรทัดที่ 11: การเปิดเคอร์เซอร์โดยใช้ DBMS_SQL.OPEN_CURSOR มันจะส่งคืนรหัสเคอร์เซอร์ที่เปิดอยู่
- รหัสบรรทัดที่ 12: หลังจากเปิดเคอร์เซอร์แล้ว SQL จะถูกแยกวิเคราะห์
- รหัสบรรทัดที่ 13: ตัวแปรผูก '1001' กำลังกำหนดให้กับรหัสเคอร์เซอร์แทน ':empno'
- รหัสบรรทัด 14-17: การกำหนดชื่อคอลัมน์ตามตำแหน่งที่สัมพันธ์กันในคำสั่ง SQL ในกรณีของเรา ตำแหน่งสัมพันธ์คือ (1) emp_name, (2) emp_no (3) เงินเดือน (4) ผู้จัดการ ตามตำแหน่งนี้ เรากำลังกำหนดตัวแปรเป้าหมาย
- รหัสบรรทัดที่ 18: การดำเนินการค้นหาโดยใช้ DBMS_SQL.EXECUTE ส่งคืนจำนวนบันทึกที่ประมวลผล
- รหัสบรรทัด 19-33: ดึงข้อมูลบันทึกโดยใช้การวนซ้ำและแสดงข้อมูลเดียวกัน
- รหัสบรรทัด 20: DBMS_SQL.FETCH_ROWS จะดึงข้อมูลหนึ่งระเบียนจากแถวที่ประมวลผล สามารถเรียกซ้ำๆ เพื่อดึงข้อมูลทุกแถวได้ หากไม่สามารถดึงข้อมูลแถวได้ ก็จะคืนค่า 0 เพื่อออกจากลูป
สรุป
ในส่วนนี้ เราได้กล่าวถึง Dynamic SQL และวิธีการดำเนินการ DYNAMIC SQL นอกจากนี้เรายังได้เห็นขั้นตอนต่างๆ ในการดำเนินการ SQL แบบไดนามิกในทั้งสองวิธี นอกจากนี้เรายังได้เห็นตัวอย่างที่มีการจัดการสถานการณ์เดียวกันทั้ง NDS และ DBMS_SQL เพื่อดำเนินการในขณะรันไทม์