動態sql

爲什麼使用動態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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章