PL 提供如下两种方法执行动态 SQL:
用 EXECUTE IMMEDIATE 子句
用游标 OPEN FOR,FETCH,CLOSE 子句
EXECUTE IMMEDIATE 子句
如果 SQL 语句是完整的,那么直接用 EXECUTE IMMEDIATE 执行即可。按照如下方式传入或者传出参数,并且需要使用占位符:
如果动态 SQL 为 SELECT 语句,而且最多返回一行记录,那么可以通过 INTO 子句指定输出参数,USING 子句指定输入参数。
如果动态 SQL 为 SELECT 语句,可能返回多条记录,那么通过 BULK COLLECT INTO 指定输出参数,USING 子句指定输入参数。
如果动态 SQL 为没有 RETURNING INTO 的 DML 子句,所有参数都通过 USING 子句传入。
如果动态 SQL 是带有 RETURNING INTO 的 DML 子句,那么用 USING 子句指定输入参数,RETURNING INTO 指定输出参数。
如下示例为利用动态 SQL,把 ID 号为 111 的员工,名字改成 Roger,并同步员工的电话:
obclient> select EMPLOYEE_ID,FIRST_NAME,PHONE_NUMBER from EMPLOYEES where EMPLOYEE_ID=111;
+-------------+------------+--------------+
| EMPLOYEE_ID | FIRST_NAME | PHONE_NUMBER |
+-------------+------------+--------------+
| 111 | Ismael | 515.124.4369 |
+-------------+------------+--------------+
1 row in set (0.00 sec)
obclient> DECLARE
-> V_ID NUMBER := 111;
-> V_NAME VARCHAR2(20) := 'Roger';
-> V_PHONE varchar2(50);
-> begin
-> execute immediate 'update employees set first_name= :NAME where employee_id = :ID
'> RETURNING PHONE_NUMBER INTO :PHONE'
-> using V_NAME, V_ID, OUT V_PHONE;
-> dbms_output.put_line(v_phone);
-> end;
-> /
Query OK, 0 rows affected (0.03 sec)
515.124.4369
obclient> select EMPLOYEE_ID,FIRST_NAME,PHONE_NUMBER from EMPLOYEES where EMPLOYEE_ID=111;
+-------------+------------+--------------+
| EMPLOYEE_ID | FIRST_NAME | PHONE_NUMBER |
+-------------+------------+--------------+
| 111 | Roger | 515.124.4369 |
+-------------+------------+--------------+
这里利用 USING 子句传入了 3 个参数,两个输入的参数,一个输出参数。
另外可以使用游标变量打开动态 SQL, 同样可以使用占位符,打开时用 USING 子句指定变量。
obclient> DECLARE
-> cv SYS_REFCURSOR;
-> query_2 VARCHAR2(200) :=
-> 'SELECT * FROM employees
'> where employee_id = :x';
-> v_employees employees%ROWTYPE;
-> BEGIN
-> OPEN cv FOR query_2 USING 111;
-> LOOP
-> FETCH cv INTO v_employees;
-> EXIT WHEN cv%NOTFOUND;
-> DBMS_OUTPUT.PUT_LINE(v_employees.employee_id||'-'||v_employees.first_name);
-> END LOOP;
-> CLOSE cv;
-> END;
-> /
Query OK, 0 rows affected (0.06 sec)
111-Ismael
OPEN FOR,FETCH,CLOSE 子句
如果动态 SQL 语句表示返回多行的 SELECT 语句,则可以使用本机动态 SQL 对其进行如下处理:
使用 OPEN FOR 语句将游标变量与动态 SQL 语句关联。 在 OPEN FOR 语句的 USING 子句中,为动态 SQL 语句中的每个占位符指定一个绑定变量。
使用 FETCH 语句一次检索一个行结果,一次检索多个结果集,或一次检索全部结果集。
使用 CLOSE 语句关闭游标变量。
如果集合符合“查询集合”中的条件,则动态 SQL 语句可以查询集合。
如下示例为在所有员工信息中检索经理级别的员工,并一次检索了行结果。
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
v_emp_cursor EmpCurTyp;
emp_record employees%ROWTYPE;
v_stmt_str VARCHAR2(200);
v_e_job employees.job%TYPE;
BEGIN
-- Dynamic SQL statement with placeholder:
v_stmt_str := 'SELECT * FROM employees WHERE job_id = :j';
-- Open cursor & specify bind variable in USING clause:
OPEN v_emp_cursor FOR v_stmt_str USING 'MANAGER';
-- Fetch rows from result set one at a time:
LOOP
FETCH v_emp_cursor INTO emp_record;
EXIT WHEN v_emp_cursor%NOTFOUND;
END LOOP;
-- Close cursor:
CLOSE v_emp_cursor;
END;
/