Oracle PLSQL

1、动态SQL

不是在Designer Time写的SQL,而是可以在运行时临时拼接起来的SQL语句; 动态SQL可以使用Oracle 内置包 DBMS_SQL 来执行,也可以使用EXECUTE IMMEDIATE 语句来执行

  1. CREATE OR REPLACE PROCEDURE delete_all_rows
  2. (p_tab_name IN VARCHAR2, p_rows_del OUT NUMBER)
  3. IS
  4. cursor_name INTEGER;
  5. BEGIN
  6. cursor_name := DBMS_SQL.OPEN_CURSOR;
  7. DBMS_SQL.PARSE(cursor_name, 'DELETE FROM '||p_tab_name,
  8. DBMS_SQL.NATIVE );
  9. p_rows_del := DBMS_SQL.EXECUTE (cursor_name);
  10. DBMS_SQL.CLOSE_CURSOR(cursor_name);
  11. END;
  12. /

1,EXECUTE IMMEDIATE执行例子

  1. CREATE PROCEDURE del_rows
  2. (p_table_name IN VARCHAR2,
  3. p_rows_deld OUT NUMBER)
  4. IS
  5. BEGIN
  6. EXECUTE IMMEDIATE 'delete from '||p_table_name;
  7. p_rows_deld := SQL%ROWCOUNT;
  8. END;
  9. /

2,动态SQL实际应用例子

POS基础数据同步并发程序 dpos_base_sync.pck

A.动态SQL的好处

在某些应用环境中可以做到灵活配置,避免因为添加一种业务而更改代码或者新建代码;

B.动态SQL的缺点

调试及阅读理解困难

2、程序中执行DDL

在程序中执行DDL,可使用Oracle 内置包:DBMS_DDL

1,在程序中执行编译命令

  1. DBMS_DDL.ALTER_COMPILE('PROCEDURE','A_USER','QUERY_EMP')

2,在程序中执行数据收集命令

  1. DBMS_DDL.ANALYZE_OBJECT('TABLE','A_USER','JOBS','COMPUTE')

3、Oracle数据库JOB

定义JOB 可以定期执行某个程序
应用场景:比如每隔一周对某些表进行数据收集,以确保CBO正确,又比如在消息处理机制中,每隔5分钟对 消息队列进行扫描处理等。
Oracle提供内置包 DBMS_JOB,可完成JOB的定义、提交、更改、停止、移除。

例子1:提交一个JOB 每隔1天执行一次

  1. DECLARE
  2. jobno NUMBER;
  3. BEGIN
  4. DBMS_JOB.SUBMIT (
  5. job => jobno ,
  6. what => 'OVER_PACK.ADD_DEPT(''EDUCATION'',2710);',
  7. next_date => TRUNC(SYSDATE + 1),
  8. interval => 'TRUNC(SYSDATE + 1)'
  9. );
  10. dbms_output.put_line(„job_no =„ || jobno )
  11. COMMIT;
  12. END;

例子2:更改JOB的执行频率为:每4小时执行一次

  1. BEGIN
  2. DBMS_JOB.CHANGE(1, NULL, TRUNC(SYSDATE+1)+6/24, SYSDATE+4/24');
  3. END;

查找自己提交的JOB号

  1. SELECT job, log_user, next_date, next_sec, broken, what FROM DBA_JOBS;

4、PLSQL中读写外部文件

Oracle 提供内置包UTL_FILE来读写外部文件,其一般处理过程为
image.png

UTL_FILE应用举例

  1. CREATE OR REPLACE PROCEDURE sal_status
  2. (p_filedir IN VARCHAR2, p_filename IN VARCHAR2)
  3. IS
  4. v_filehandle UTL_FILE.FILE_TYPE;
  5. CURSOR emp_info IS
  6. SELECT last_name, salary, department_id
  7. FROM employees
  8. ORDER BY department_id;
  9. v_newdeptno employees.department_id%TYPE;
  10. v_olddeptno employees.department_id%TYPE := 0;
  11. BEGIN
  12. v_filehandle := UTL_FILE.FOPEN (p_filedir, p_filename,'w');
  13. UTL_FILE.PUTF (v_filehandle,'SALARY REPORT: GENERATED ON
  14. %s\n', SYSDATE);
  15. UTL_FILE.NEW_LINE (v_filehandle);
  16. FOR v_emp_rec IN emp_info LOOP
  17. v_newdeptno := v_emp_rec.department_id;
  18. ...
  19. ...
  20. IF v_newdeptno <> v_olddeptno THEN
  21. UTL_FILE.PUTF (v_filehandle, 'DEPARTMENT: %s\n',
  22. v_emp_rec.department_id);
  23. END IF;
  24. UTL_FILE.PUTF (v_filehandle,' EMPLOYEE: %s earns: %s\n',
  25. v_emp_rec.last_name, v_emp_rec.salary);
  26. v_olddeptno := v_newdeptno;
  27. END LOOP;
  28. UTL_FILE.PUT_LINE (v_filehandle, '*** END OF REPORT ***');
  29. UTL_FILE.FCLOSE (v_filehandle);
  30. EXCEPTION
  31. WHEN UTL_FILE.INVALID_FILEHANDLE THEN
  32. RAISE_APPLICATION_ERROR (-20001, 'Invalid File.');
  33. WHEN UTL_FILE.WRITE_ERROR THEN
  34. RAISE_APPLICATION_ERROR (-20002, 'Unable to write to file');
  35. END sal_status;
  36. /