EXECUTE语句
EXECUTE语句用于调用存储过程或包,存储过程或块语句中若包含DDL语句,需使用特定EXECUTE语句(EXECUTE IMMEDIATE)进行。
说明:
CALL语句同EXECUTE语句语法,只需替换关键字即可。
主要语法结构
语法格式
sql
ExecuteStmt::=
[schema_name.] name_space [( func_params )]
| EXECUTE [schema_name.] name_space
| EXECUTE [schema_name.] name_space ( func_params )
| EXECUTE IMMEDIATE b_expr [ USING ColId [,ColId]... ] [RETURNING | BULK COLLECT | RETURNING BULK COLLECT] [INTO ColId [,ColId]...] [LIMIT ICONST]
参数说明
schema_name
:模式名,可省略,跨模式执行存储过程/函数时需获取执行权限。name_space
:存储过程名、存储函数名、包中定义的存储过程名或存储函数名,其中如果调用包中存储过程或存储函数则需加包名,仅存储过程或函数可直接使用过程名或函数名进行调用。USING
:在执行动态SQL语句时对参数列表进行绑定,该参数后的参数列表与动态SQL语句中的占位符进行绑定。RETURNING
:将插入、更新和删除受影响的行返回,通常与INTO子句搭配使用,INTO子句保存和记录插入、更新和删除受影响的行的数据,若无INTO子句则表示仅返回受影响的行但不记录受影响行的数据,此处仅表示单个的变量或集合数据。BULK COLLECT
:单个集合变量或多个集合变量的多记录可使用BULK COLLECT。RETURNING BULK COLLECT
:可以出现在插入、更新、删除或执行即时语句中。使用该子句可将其结果集存储在一个或多个集合中。
参数信息func_params
语法格式
sql
func_params::=
{b_expr | param_name => b_expr}
| func_params , {b_expr | param_name => b_expr}
| /*EMPTY*/
参数说明
func_params
:参数值,根据指定的参数类型进行传值,支持两种方式传值,包括直接指定参数值b_expr、参数值与形参名绑定传值param_name=>b_expr,其中param_name为形参名,同一个过程或函数参数两种方式不可混用。/*EMPTY*/
:空参数。
说明:
存储过程或函数参数的类型可以指定为in、out、in out三种模式。
示例
动态SQL
定义一个test_exec表与一个execute_proc存储过程,存储过程含2个输入参数x与y,过程体定义一个string变量用于初始化记录入库语句,然后将输入参数值赋值给入库语句进行执行。通过执行存储过程,实现将参数值1与TEST插入到test_exec表,最后查询表记录确认存储过程执行正确性。
sql
-- 创建表
CREATE TABLE test_exec(id INT,name VARCHAR(20));
-- 创建存储过程
CREATE OR REPLACE PROCEDURE execute_proc(x IN INTEGER, y IN CHAR(10))
AS
string VARCHAR2(100);
BEGIN
string := 'INSERT INTO test_exec VALUES(?, ?);';
EXECUTE IMMEDIATE string USING x, y;
END;
/
-- 调用存储过程
EXECUTE execute_proc(1,'TEST_EXEC');
-- 查询表
SELECT * FROM test_exec;
ID | NAME |
------------------------------------------------------------------------------
1 | TEST_EXEC|
RETURNING INTO
将ID为100的员工薪水提高10%,保留旧薪水记录,使用RETURNING INTO将更新后的last_name和salary值存入emp_info记录,最后输出。
sql
-- 创建表
CREATE TABLE emp_ret (employee_id INT, last_name VARCHAR(30), salary NUMERIC(15,3));
-- 插入数据
INSERT INTO emp_ret VALUES(100,'King',31944)(101,'Kochhar',18700)(102,'De Haan',18700)(103,'Hunold',9900);
DECLARE
-- 定义一个记录类型
TYPE emp_rec IS RECORD (
last_name emp_ret.last_name%TYPE,
salary emp_ret.salary%TYPE
);
-- 声明一个记录类型的变量
emp_info emp_rec;
-- 声明一个变量来存储旧的薪水
old_salary emp_ret.salary%TYPE;
BEGIN
-- 查询员工ID为100的旧薪水
SELECT salary INTO old_salary FROM emp_ret WHERE employee_id = 100;
-- 更新员工ID为100的薪水,并返回更新后的姓名和薪水
UPDATE emp_ret
SET salary = salary * 1.1
WHERE employee_id = 100
RETURNING last_name, salary INTO emp_info;
-- 输出更新后的信息
DBMS_OUTPUT.PUT_LINE('Salary of ' || emp_info.last_name || ' raised from ' || old_salary || ' to ' || emp_info.salary);
END;
/
-- 输出结果
Salary of King raised from 31944 to 35138.4
BULK COLLECT INTO
创建一个表emp_ret1,向其中插入一些数据,并查询特定条件下的所有员工信息。将这些信息通过BULK COLLECT INTO收集到一个集合类型中,并通过循环输出每个符合条件的员工的姓名和薪水。
sql
-- 创建表
CREATE TABLE emp_ret1(employee_id INT, last_name VARCHAR(30), salary NUMERIC(15,3));
-- 插入数据
INSERT INTO emp_ret1 VALUES(100, 'King', 31944)(101, 'Kochhar', 18700)(102, 'De Haan', 18700)(103, 'Hunold', 9900);
DECLARE
-- 定义一个集合类型,元素类型为emp_ret1表的行类型
TYPE em_tp IS TABLE OF emp_ret1%ROWTYPE;
-- 声明一个集合变量
emp_tb em_tp;
-- 定义一个字符串变量,用于存储动态SQL查询语句
str VARCHAR(100);
BEGIN
-- 构建动态SQL查询语句
str := 'SELECT * FROM emp_ret1 WHERE employee_id < :id';
-- 执行动态SQL查询,并将结果批量收集到集合中
EXECUTE IMMEDIATE str BULK COLLECT INTO emp_tb USING 103;
-- 遍历集合并输出每个员工的姓名和薪水
FOR i IN 1..emp_tb.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Name of ' || emp_tb(i).last_name || ' salary is ' || emp_tb(i).salary);
END LOOP;
END;
/
-- 输出结果
Name of King salary is 31944
Name of Kochhar salary is 18700
Name of De Haan salary is 18700
RETURNING BULK COLLECT INTO
创建一个表emp_ret2,向其中插入一些数据,并删除特定条件下的员工记录。同时使用RETURNING BULK COLLECT INTO将删除的记录信息收集到集合中,并输出删除的记录信息。
sql
-- 创建表
CREATE TABLE emp_ret2(employee_id INT, last_name VARCHAR(30), salary NUMERIC(15,3));
-- 插入数据
INSERT INTO emp_ret2 VALUES(100, 'King', 31944)(101, 'Kochhar', 18700)(102, 'De Haan', 18700)(103, 'Hunold', 9900);
DECLARE
-- 定义集合类型
TYPE num_list IS TABLE OF emp_ret2.employee_id%TYPE;
TYPE num_list1 IS TABLE OF emp_ret2.last_name%TYPE;
-- 声明集合变量
enums num_list;
names num_list1;
BEGIN
-- 删除记录并收集返回值
DELETE FROM emp_ret2
WHERE employee_id < 102
RETURNING employee_id, last_name BULK COLLECT INTO enums, names;
-- 输出删除记录的数量
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows:');
-- 遍历集合并输出每个删除记录的信息
FOR i IN enums.FIRST .. enums.LAST LOOP
DBMS_OUTPUT.PUT_LINE('Employee #' || enums(i) || ': ' || names(i));
END LOOP;
END;
/
-- 输出结果:
Deleted 2 rows:
Employee #100: King
Employee #101: Kochhar