爲什麼使用動態sql,因爲plsql塊中不能定義create等表結構操作語句;
注意:
1.動態sql結束不能有分號;
2.不能用單引號,要使用雙引號
方式一:DBMS_SQL.PARSE
declare
cursor_name INTEGER;
BEGIN
cursor_name := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursor_name, 'select * from employees',DBMS_SQL.NATIVE );
dbms_output.put_line(DBMS_SQL.EXECUTE (cursor_name));
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
方式二: execute immediate
create or replace procedure query_dep_all_salary
(dep_id in number default -1,
emp_count out number,
all_salary out number)
is
begin
--下面這句中帶冒號的變量自動與using中的變量匹配;
--into 的作用,和select中的into作用一致
execute immediate 'select count(*), sum(salary) from employees group by department_id having department_id = :d_id'
into emp_count, all_salary
using dep_id;
end;
--測試
declare
v_dep_id number := 60;
v_emp_count number := 0;
v_all_salary number := 0;
begin
query_dep_all_salary(dep_id => v_dep_id, all_salary => v_all_salary, emp_count => v_emp_count);
dbms_output.put_line('部門ID爲'||v_dep_id||'的工資總額爲'||v_all_salary||'元,員工總數爲'||v_emp_count||'人');
end;
動態sql多行查詢
create or replace procedure query_dep_all_emp
(dep_id number)
is
type t_cursor is ref cursor;--定義遊標類型
v_sql_statement varchar2(200);
v_emp_row employees%rowtype;
cursor_dep t_cursor;
begin
v_sql_statement := 'select * from employees where department_id = :d_id';
open cursor_dep
for v_sql_statement
using dep_id;
loop
fetch cursor_dep into v_emp_row;
exit when cursor_dep%NOTFOUND;
dbms_output.put_line(v_emp_row.first_name);
end loop;
end;
應用:寫一個匿名塊,創建一張臨時表,hand_teacher_temp, 結構與 hand_teacher 相同。
取所有課程及格率高於50%的教師信息,插入到 hand_teacher_temp
declare
v_sql_create_temp varchar2(500);
cursor cursor_teacher is
select *
from hand_teacher teacher
where teacher.teacher_no in
(select distinct teacher.teacher_no
from hand_teacher teacher,
hand_student_core core,
hand_course course
where teacher.teacher_no = course.teacher_no
and course.course_no = core.course_no
and (select count(*)
from hand_student_core core,
hand_teacher teacher,
hand_course course
where (core.core > 60 or core.core = 60)
and core.course_no = course.course_no
and course.teacher_no = teacher.teacher_no) >
(select count(*)
from hand_student_core core, hand_teacher teacher
where core.core < 60
and core.course_no = course.course_no
and course.teacher_no = teacher.teacher_no));
begin
--創建臨時表
v_sql_create_temp := '
create global temporary table hand_teacher_temp
(TEACHER_NO VARCHAR2(10),
TEACHER_NAME VARCHAR2(20),
MANAGER_NO VARCHAR2(10))
on commit delete rows';
execute immediate v_sql_create_temp;
for teacher_temp in cursor_teacher loop
--此處必須使用動態sql插入數據,不知道爲什麼
--如果直接使用insert會提示臨時表沒有創建
execute immediate 'insert into hand_teacher_temp values(:1, :2, :3)'
using teacher_temp.TEACHER_NO,teacher_temp.TEACHER_NAME,teacher_temp.MANAGER_NO;
end loop;
end;