最近项目在做版本升级,涉及到原有功能的表结构修改,需要将旧数据转移到新库中,项目上定的方案是在旧数据库中通过存储过程生成新数据库的INSERT
语句。故对此块内容做了复习整理。
声明变量
--格式:变量名 数据类型;
v_name VARCHAR2(128);
声明常量
--格式: 变量名 CONSTRANT 数据类型 := value;
v_days_in_year CONSTRANT INTEGER := 365;
PL/SQL 数据类型
执行部分逻辑是按从上到下的顺序执行的,PL/SQL 支持条件选择语句、循环语句
IF 语句最简形式
IF condition THEN
DBMS_OUTPUT.PUT_LINE('当condition为TRUE时,执行');
END IF;
IF 语句扩展形式
IF condition1 THEN
DBMS_OUTPUT.PUT_LINE('当condition1为TRUE时,执行');
ELSIF condition2 THEN
DBMS_OUTPUT.PUT_LINE('当condition2为TRUE时,执行');
ELSE
DBMS_OUTPUT.PUT_LINE('当condition1为FALSE且condition2为FALSE时,执行');
END IF;
一个IF
语句最多只能有一个ELSE
分支,可以有0个
或多个
ELSIF condition THEN
分支
CASE 语句最简形式
CASE age
WHEN 10 THEN
DBMS_OUTPUT.PUT_LINE('当age值为10时,执行');
END CASE;
CASE 语句扩展形式
CASE age
WHEN 10 THEN
DBMS_OUTPUT.PUT_LINE('当age值为10时,执行');
WHEN 20 THEN
DBMS_OUTPUT.PUT_LINE('当age值为20时,执行');
WHEN 30 THEN
DBMS_OUTPUT.PUT_LINE('当age值为30时,执行');
ELSE
DBMS_OUTPUT.PUT_LINE('当age值为其它值时,执行');
END CASE;
一个CASE
语句最多只能有一个ELSE
分支,可以有一个或多个WHEN THEN
分支
CASE 语句变形
CASE
WHEN age = 10 THEN
DBMS_OUTPUT.PUT_LINE('当age值为10时,执行');
WHEN age = 20 THEN
DBMS_OUTPUT.PUT_LINE('当age值为20时,执行');
WHEN age = 30 THEN
DBMS_OUTPUT.PUT_LINE('当age值为30时,执行');
ELSE
DBMS_OUTPUT.PUT_LINE('当age值为其它值时,执行');
END CASE;
CASE 语句赋值给变量,THEN
后面的语句不要加;
appraisal :=
CASE
WHEN grade = 'A' THEN '优'
WHEN grade = 'B' THEN '良'
WHEN grade = 'C' THEN '差'
ELSE ''
END CASE;
LOOP
num NUMBER := 0;
total NUMBER := 0;
LOOP
num := num + 1;
total := total + num;
EXIT WHEN num = 10;--当num=10时,退出循环
END LOOP;
DBMS_OUTPUT.PUT_LINE(total);
--退出循环
EXIT WHEN condition;
--退出当前循环进入下一次循环
CONTINUE WHEN condition;
FOR
FOR item IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(item);
END LOOP;
每次迭代的步长都是1,当在IN
关键字后面加上REVERSE
关键字时,将反转遍历的顺序,在上例中将变为从10~1
WHILE
WHILE condition LOOP
DBMS_OUTPUT.PUT_LINE();
condition := FALSE;
END LOOP;
声明记录
--格式: 变量名 表名.字段名%TYPE;
v_name employee.name%TYPE;
--格式: 变量名 表名%ROWTYPE;
v_row employee%ROWTYPE;
表名.字段名%TYPE : 用于单个字段
表名%ROWTYPE : 用于表中的一行记录
使用以上两种方式定义变量的数据类型,使声明的变量的数据类型将与指定表中指定的字段的数据类型始终保持一致
如果我们需要定义一个变量存储多个字段(大于一个字段但小于表中的全部字段 或 多个字段来自多个表)的值时,我们可以声明一个record type
TYPE employeeAddrType IS RECORD(
name VARCHAR2(128),
addr VARCHAR2(256)
);
v_employee_adr employeeAddrType;
游标
游标的使用由以下几步操作构成:
DECLARE
--声明游标
CURSOR my_cursor IS SELECT * FROM employee;
BEGIN
--打开游标
OPEN my_cursor;
--逻辑处理
LOOP
EXIT WHEN my_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(my_cursor.name);
END LOOP;
--关闭游标
CLOSE my_cursor;
END;
将游标中的数据赋值到指定的变量中
FETCH my_cursor INTO v_row;
使用游标更新数据时,在声明游标的结尾需要使用FOR UPDATE
,例如:
CURSOR my_cursor IS SELECT * FROM employee FOR UPDATE;
在逻辑处理部分的UPDATE
语句中使用WHERE CURRENT OF 游标名
指定更新当前行
UPDATE employee SET name = name||'TEST' WHERE CURRENT OF my_cursor;
如何传参到游标中呢?
在游标声明处指定参数,例如:
CURSOR my_cursor(v_id employee.id%TYPE) IS SELECT * FROM employee WHERE id=v_id;
声明了变量后如何使用呢,在打开游标处设置参数值
OPEN my_cursor(1);
过程
CREATE OR REPLACE PROCEDURE procedure_name
IS
--声明变量
BEGIN
--逻辑处理
END procedure_name;
上面的存储过程是无参的,而实际工作中我们可能会遇到需要传参或返回值的情况
参数有三种模式,分为:
CREATE OR REPLACE PROCEDURE procedure_name(
business_type in varchar2(4),
apply_code in varchar2(32),
business_stauts out varchar2(4)
) IS
--声明变量
v_business_status varchar2(4);
v_sql varchar2(200);
BEGIN
--逻辑处理
v_sql := 'SELECT business_status INTO v_business_status FROM dp_c_business_apply where business_type = '''||business_type||''' and apply_code = '''||apply_code||'';'
execute immediate v_sql;
business_status := v_business_status;
END procedure_name;
调用存储过程
DECLARE
v_status varchar2(200);
BEGIN
EXECUTE procedure_name('BS01','201907200000001',v_status);
END;
在上面的例子中我们是按各参数的位置进行传值的,我们还可以按参数名称进行传值
v_status varchar2(200);
BEGIN
EXECUTE procedure_name(business_type=>'BS01',apply_code=>'201907200000001',business_status=>business_status);
END;