Oracle 11g Release 1 (11.1) PL/SQL_了解静态和动态 SQL

http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#BABGEDAE

http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/dynamic.htm#CACDDACH

本文内容

  • 静态 SQL
  • 动态 SQL

静态 SQL

静态 SQL 是属于 PL/SQL 语言的 SQL。也就是:

  • 除了解释执行计划的,数据操作语句(Data Manipulation Language,DML)
  • 事务控制(Transaction Control Language,TCL)语句
  • SQL 函数
  • SQL 伪列
  • SQL 运算符

静态 SQL 符合目前 ANSI/ISO SQL 标准。

示例 1:演示用 PL/SQL 操作数据

若操作数据库的数据,则无需任何特别的符号,你可以直接在 PL/SQL 程序里包含 DML 操作,如 INSERTUPDATEDELETE 语句。你也可以直接在 PL/SQL 程序里包含 COMMIT 语句。

CREATE TABLE employees_temp
  AS SELECT employee_id, first_name, last_name 
  FROM employees;
DECLARE
  emp_id          employees_temp.employee_id%TYPE;
  emp_first_name  employees_temp.first_name%TYPE;
  emp_last_name   employees_temp.last_name%TYPE;
BEGIN
   INSERT INTO employees_temp VALUES(299, 'Bob', 'Henry');
   UPDATE employees_temp
     SET first_name = 'Robert' WHERE employee_id = 299;
   DELETE FROM employees_temp WHERE employee_id = 299 
     RETURNING first_name, last_name
       INTO emp_first_name, emp_last_name;
   COMMIT;
   DBMS_OUTPUT.PUT_LINE( emp_first_name  || ' ' || emp_last_name);
END;
/

示例 2:演示在 PL/SQL 调用 SQL 函数——COUNT 函数

DECLARE
  job_count NUMBER;
  emp_count NUMBER;
BEGIN
  SELECT COUNT(DISTINCT job_id)
    INTO job_count
      FROM employees;
 
  SELECT COUNT(*)
    INTO emp_count
      FROM employees;
END;
/

示例 3:演示使用伪列——ROWNUM

CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
   CURSOR c1 IS SELECT employee_id, salary FROM employees_temp
      WHERE salary > 2000 AND ROWNUM <= 10;  -- 10 arbitrary rows
   CURSOR c2 IS SELECT * FROM
     (SELECT employee_id, salary FROM employees_temp
       WHERE salary > 2000 ORDER BY salary DESC)
     WHERE ROWNUM < 5;  -- first 5 rows, in sorted order
BEGIN
-- Each row gets assigned a different number
  UPDATE employees_temp SET employee_id = ROWNUM;
END;
/

动态 SQL

动态 SQL 是用编程的方式在运行时创建并执行 SQL 语句。这在编写通用或灵活的程序,像 ad hoc 查询系统,或在编写必须执行 DLL 语句的程序,或是在编译期间不确定整个 SQL 文本、数量,以及输入输出变量的数据类型时,很有用。

PL/SQL 提供两种方式编写动态 SQL:

  • 本地动态 SQL(Native dynamic SQL),创建并执行动态 SQL 语句是 PL/SQL 语言的特点
  • DBMS_SQL 包是创建、执行和描述动态 SQL 语言的 API

Native dynamic SQL 代码比其等价的使用 DBMS_SQL package 代码更容易读写,执行也快。特别是,当它通过编译器优化后。然而,若编写 Native dynamic SQL 代码,你必须在编译期间知道输入和输出变量的数据类型和数量。否则,只能使用 DBMS_SQL package

当你同时需要 Native dynamic SQLDBMS_SQL package 时,你可以通过 DBMS_SQL.TO_REFCURSOR 函数和 DBMS_SQL.TO_CURSOR_NUMBER 函数在它们之间进行切换。

何时使用静态 SQL 或动态 SQL

在 PL/SQL,下面情况需要动态 SQL:

  • 编译期间无法确定 SQL 文本。例如,SELECT 语句包含一个事先不确定的标识符,如表名,或是 WHERE 子句中的一部分在编译期间不确定。
  • 静态 SQL不支持的。也就是不能用静态 SQL 创建的任何 SQL。

若不需要动态 SQL,则使用静态 SQL 的好处如下:

  • 成功的编译会验证静态 SQL 引用可靠的数据库对象,以及访问这些对象的必需权限。
  • 成功的编译会创建模式对象依赖。

示例 4:演示从动态 PL/SQL 块调用一个子程序

-- Subprogram that dynamic PL/SQL block invokes:
CREATE PROCEDURE create_dept ( deptid IN OUT NUMBER,
                               dname  IN VARCHAR2,
                               mgrid  IN NUMBER,
                               locid  IN NUMBER
                             ) AS
BEGIN
deptid := departments_seq.NEXTVAL;
  INSERT INTO departments VALUES (deptid, dname, mgrid, locid);
END;
/
DECLARE
  plsql_block VARCHAR2(500);
  new_deptid  NUMBER(4);
  new_dname   VARCHAR2(30) := 'Advertising';
  new_mgrid   NUMBER(6)    := 200;
  new_locid   NUMBER(4)    := 1700;
BEGIN
 -- Dynamic PL/SQL block invokes subprogram:
  plsql_block := 'BEGIN create_dept(:a, :b, :c, :d); END;';
 
 /* Specify bind arguments in USING clause.
    Specify mode for first parameter.
    Modes of other parameters are correct by default. */
  EXECUTE IMMEDIATE plsql_block
    USING IN OUT new_deptid, new_dname, new_mgrid, new_locid;
END;
/

原文地址:https://www.cnblogs.com/liuning8023/p/2506987.html