Cursores no Oracle PL/SQL são estruturas que permitem executar consultas SQL e processar seus resultados linha por linha, facilitando o controle de dados e operações DML.
Cursores Explícitos
Cursores explícitos são definidos pelo programador para cnosultas específicas. Existem várias formas de declarar variáveis associadas.
1. Declaração Estática de Variáveis
DECLARE CURSOR c_func IS SELECT cod, nome, salario FROM funcionarios;
v_cod NUMBER;
v_nome VARCHAR2(20);
v_sal NUMBER;
BEGIN
OPEN c_func;
LOOP
FETCH c_func INTO v_cod, v_nome, v_sal;
EXIT WHEN c_func%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Código: ' || v_cod || ', Nome: ' || v_nome || ', Salário: ' || v_sal);
END LOOP;
CLOSE c_func;
END;
/
2. Declaração Dinâmica com %type
DECLARE CURSOR c_emp IS SELECT empno, ename, sal FROM emp;
v_id emp.empno%TYPE;
v_nome emp.ename%TYPE;
v_salario emp.sal%TYPE;
BEGIN
OPEN c_emp;
FETCH c_emp INTO v_id, v_nome, v_salario;
WHILE c_emp%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('ID: ' || v_id || ', Nome: ' || v_nome || ', Salário: ' || v_salario);
FETCH c_emp INTO v_id, v_nome, v_salario;
END LOOP;
CLOSE c_emp;
END;
/
3. Uso de %rowtype para Linhas
DECLARE CURSOR c_dados IS SELECT * FROM emp;
reg emp%ROWTYPE;
BEGIN
OPEN c_dados;
FOR i IN 1..1000 LOOP
FETCH c_dados INTO reg;
IF c_dados%NOTFOUND THEN EXIT; END IF;
DBMS_OUTPUT.PUT_LINE('Número: ' || reg.empno || ', Nome: ' || reg.ename);
END LOOP;
CLOSE c_dados;
END;
/
4. Métodos de Loop Altenrativos
Cursors podem ser iterados usando diferentes estruturas de loop.
-- Loop FOR implícito
DECLARE CURSOR c_sal IS SELECT ename, sal FROM emp WHERE sal BETWEEN 1000 AND 2000;
BEGIN
FOR rec IN c_sal LOOP
DBMS_OUTPUT.PUT_LINE('Funcionário: ' || rec.ename || ', Salário: ' || rec.sal);
END LOOP;
END;
/
5. Cursores com Parâmetros
DECLARE CURSOR c_filtra(v_dept NUMBER, v_cargo VARCHAR2) IS
SELECT ename FROM emp WHERE deptno = v_dept AND job = v_cargo;
BEGIN
FOR v_res IN c_filtra(20, 'ANALYST') LOOP
DBMS_OUTPUT.PUT_LINE('Encontrado: ' || v_res.ename);
END LOOP;
END;
/
6. Cursores Atualizáveis
DECLARE CURSOR c_update IS SELECT * FROM funcionarios FOR UPDATE;
BEGIN
FOR v_linha IN c_update LOOP
IF v_linha.salario < 1500 THEN
UPDATE funcionarios SET salario = salario * 1.5 WHERE CURRENT OF c_update;
END IF;
END LOOP;
COMMIT;
END;
/
Cursores Implícitos
Toda instrução SQL executada no PL/SQL utiliza um cursor implícito, acessível via atributos como %FOUND e %ROWCOUNT.
BEGIN
INSERT INTO dept VALUES (50, 'Pesquisa', 'SP');
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Linhas inseridas: ' || SQL%ROWCOUNT);
END IF;
END;
/
Cursoers Dinâmicos
Cursores dinâmicos permitem que a consulta SQL seja definida em tempo de execução, com tipos fortes ou fracos.
1. Cursor Dinâmico Forte
DECLARE TYPE t_ref IS REF CURSOR RETURN emp%ROWTYPE;
c_ref t_ref;
v_emp emp%ROWTYPE;
v_cond NUMBER;
BEGIN
SELECT COUNT(*) INTO v_cond FROM emp WHERE job = 'MANAGER';
IF v_cond > 0 THEN
OPEN c_ref FOR SELECT * FROM emp WHERE job = 'MANAGER';
ELSE
OPEN c_ref FOR SELECT * FROM emp;
END IF;
LOOP
FETCH c_ref INTO v_emp;
EXIT WHEN c_ref%NOTFOUND;
DBMS_OUTPUT.PUT_line('Dados: ' || v_emp.ename || ' - ' || v_emp.sal);
END LOOP;
CLOSE c_ref;
END;
/
2. Cursor Dinâmico Fraco
DECLARE TYPE t_generico IS REF CURSOR;
c_cursor t_generico;
v_tab1 emp%ROWTYPE;
v_tab2 dept%ROWTYPE;
v_opcao VARCHAR2(10) := 'EMP';
BEGIN
IF v_opcao = 'EMP' THEN
OPEN c_cursor FOR SELECT * FROM emp;
FETCH c_cursor INTO v_tab1;
WHILE c_cursor%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('Emp: ' || v_tab1.ename);
FETCH c_cursor INTO v_tab1;
END LOOP;
ELSE
OPEN c_cursor FOR SELECT * FROM dept;
FETCH c_cursor INTO v_tab2;
WHILE c_cursor%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('Dept: ' || v_tab2.dname);
FETCH c_cursor INTO v_tab2;
END LOOP;
END IF;
CLOSE c_cursor;
END;
/