Manipulação de Cursores no Oracle PL/SQL

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;
/

Tags: Oracle PL/SQL cursores banco de dados Consultas Dinâmicas

Publicado em 7-4 18:22