条件与循环
- FOR i IN REVERSE 3 .. 1 LOOP 可以倒序
- CONTINUE 跳过本次循环,EXIT 跳出循环
- 避免 GOTO,它会让逻辑难以追踪
DECLARE
v_sal NUMBER := 12000;
v_grade VARCHAR2(10);
v_i NUMBER := 1;
BEGIN
-- IF / ELSIF
IF v_sal < 5000 THEN
v_grade := '低';
ELSIF v_sal < 15000 THEN
v_grade := '中';
ELSE
v_grade := '高';
END IF;
-- CASE 表达式
v_grade := CASE
WHEN v_sal < 5000 THEN '低'
WHEN v_sal < 15000 THEN '中'
ELSE '高'
END;
-- 1) 基础 LOOP
LOOP
EXIT WHEN v_i > 3;
v_i := v_i + 1;
END LOOP;
-- 2) WHILE
v_i := 1;
WHILE v_i <= 3 LOOP
v_i := v_i + 1;
END LOOP;
-- 3) FOR(推荐:自动控制上下界)
FOR i IN 1 .. 3 LOOP
DBMS_OUTPUT.PUT_LINE('第 ' || i || ' 次');
END LOOP;
DBMS_OUTPUT.PUT_LINE('等级: ' || v_grade);
END;
/只作示例阅读:5 行写入限制下不执行任意 PL/SQL、循环写入或动态 SQL;只开放字面量 DBMS_OUTPUT 打印。请在独立学习数据库中练习。
隐式游标属性
- SQL%FOUND / SQL%NOTFOUND / SQL%ROWCOUNT / SQL%ISOPEN 是隐式游标属性
- 它们反映最近一条 DML 或 SELECT INTO 的结果
- SQL%ROWCOUNT 在 SELECT INTO 成功时为 1
BEGIN
UPDATE employees SET salary = salary * 1.05 WHERE department_id = 60;
IF SQL%ROWCOUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE('没有匹配的行,未做任何修改');
ROLLBACK;
ELSE
DBMS_OUTPUT.PUT_LINE('更新了 ' || SQL%ROWCOUNT || ' 行');
ROLLBACK;
-- 演示用,不留痕
END IF;
END;
/只作示例阅读:5 行写入限制下不执行任意 PL/SQL、循环写入或动态 SQL;只开放字面量 DBMS_OUTPUT 打印。请在独立学习数据库中练习。
显式游标与游标 FOR 循环
DECLARE
CURSOR c_emp IS
SELECT employee_id, last_name, salary
FROM employees
WHERE department_id = 60
ORDER BY salary DESC;
v_id employees.employee_id%TYPE;
v_name employees.last_name%TYPE;
v_sal employees.salary%TYPE;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO v_id, v_name, v_sal;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_id || ' ' || v_name || ' ' || v_sal);
END LOOP;
CLOSE c_emp;
END;
/只作示例阅读:5 行写入限制下不执行任意 PL/SQL、循环写入或动态 SQL;只开放字面量 DBMS_OUTPUT 打印。请在独立学习数据库中练习。
BEGIN
FOR r IN (SELECT employee_id, last_name, salary
FROM employees
WHERE department_id = 60
ORDER BY salary DESC) LOOP
DBMS_OUTPUT.PUT_LINE(r.employee_id || ' ' || r.last_name || ' ' || r.salary);
END LOOP;
END;
/游标 FOR 循环自动 OPEN、FETCH、CLOSE,还自动声明记录变量 r,出错也会自动关闭游标。
只作示例阅读:5 行写入限制下不执行任意 PL/SQL、循环写入或动态 SQL;只开放字面量 DBMS_OUTPUT 打印。请在独立学习数据库中练习。
参数化游标与 FOR UPDATE
DECLARE
CURSOR c_dept_sal (p_dept NUMBER, p_min NUMBER) IS
SELECT employee_id, salary
FROM employees
WHERE department_id = p_dept
AND salary >= p_min
FOR UPDATE OF salary;
-- 锁定这些行,防止并发修改
BEGIN
FOR r IN c_dept_sal(60, 5000) LOOP
DBMS_OUTPUT.PUT_LINE(r.employee_id || ' -> ' || r.salary);
END LOOP;
ROLLBACK;
END;
/只作示例阅读:5 行写入限制下不执行任意 PL/SQL、循环写入或动态 SQL;只开放字面量 DBMS_OUTPUT 打印。请在独立学习数据库中练习。