One of the errors in your procedure was trying to use:
FETCH v_curs INTO spr_id, spr_name, spr_family;
Where spr_id, spr_name, spr_family
are all declared as IN
parameters and cannot be written to. You would want to declare them as local variables instead.
When you want to retrieve a cursor, normally you do not open a cursor and print it to the database console immediately as that makes the procedure only useful for that one thing and most times you are going to want to return the cursor without reading it.
Instead, you would open the cursor and then return it as an OUT
parameter to the calling scope so that they can read it and, if necessary, format and output it separately. If you did want to print it to the console then you can split that off into a separate procedure:
CREATE PACKAGE cur_pkg AS
TYPE t_cur is ref cursor;
PROCEDURE open_cur_spr_ppl (
p_cur OUT SYS_REFCURSOR
);
PROCEDURE print_cur_spr_ppl (
p_cur IN SYS_REFCURSOR
);
end cur_pkg;
CREATE PACKAGE BODY cur_pkg AS
PROCEDURE open_cur_spr_ppl (
p_cur OUT SYS_REFCURSOR
)
is
begin
open p_cur for
select spravochnik_id,
spravochnik_name,
spravochnik_family
from spravochnik_people
where spravochnik_id >= 1770;
end open_cur_spr_ppl;
PROCEDURE print_cur_spr_ppl (
p_cur IN SYS_REFCURSOR
)
is
v_id spravochnik_people.spravochnik_id%TYPE;
v_name spravochnik_people.spravochnik_name%TYPE;
v_family spravochnik_people.spravochnik_family%TYPE;
c_id_width CONSTANT PLS_INTEGER := 10;
c_name_width CONSTANT PLS_INTEGER := 30;
c_family_width CONSTANT PLS_INTEGER := 30;
begin
-- Header
DBMS_OUTPUT.PUT_LINE(
LPAD('ID', c_id_width, ' ')
|| ' | ' || RPAD('NAME', c_name_width, ' ')
|| ' | ' || RPAD('FAMILY', c_family_width, ' ')
);
DBMS_OUTPUT.PUT_LINE(
LPAD(':', c_id_width, '-')
|| ' | ' || RPAD(':', c_name_width, '-')
|| ' | ' || RPAD(':', c_family_width, '-')
);
LOOP
FETCH p_cur INTO v_id, v_name, v_family;
EXIT WHEN p_cur%notfound;
DBMS_OUTPUT.PUT_LINE(
LPAD(v_id, c_id_width, ' ')
|| ' | ' || RPAD(v_name, c_name_width, ' ')
|| ' | ' || RPAD(v_family, c_family_width, ' ')
);
END LOOP;
CLOSE p_cur;
end print_cur_spr_ppl;
end cur_pkg;
Then if you want to call it you can use:
DECLARE
v_cur SYS_REFCURSOR;
BEGIN
cur_pkg.open_cur_spr_ppl(v_cur);
cur_pkg.print_cur_spr_ppl(v_cur);
END;
/
Which, for the sample data:
CREATE TABLE spravochnik_people (spravochnik_id, spravochnik_name, spravochnik_family) AS
SELECT 1800, 'Alice', 'Abbot' FROM DUAL UNION ALL
SELECT 1900, 'Betty', 'Baron' FROM DUAL;
Outputs:
ID | NAME | FAMILY
---------: | :----------------------------- | :-----------------------------
1800 | Alice | Abbot
1900 | Betty | Baron
db<>fiddle here