我正在使用Oracle XE的人力资源数据库学习PL / SQL。
我创建了以下存储过程:
CREATE OR REPLACE PROCEDURE get_employees( p_country_id IN CHAR
, p_emp OUT SYS_REFCURSOR)
IS
BEGIN
OPEN p_emp FOR
SELECT e.first_name
,e.last_name
,e.department_id
,d.department_name
,l.city
,l.state_province
FROM employees e
INNER JOIN departments d
ON e.department_id = d.department_id
INNER JOIN locations l
ON d.location_id = l.location_id
WHERE l.country_id = p_country_id;
END;
我知道如何在SQL Developer GUI界面中执行它并查看结果。我还从Justin Cave here和here了解了如何执行它并查看SQL * Plus样式的结果:
VARIABLE CE REFCURSOR;
EXEC GET_EMPLOYEES('US', :CE);
PRINT CE;
我想在匿名PL / SQL块中执行存储过程并在网格中查看结果,但它没有成功。
就像Justin Cave建议的那样,以下执行得很好,但结果不会显示:
DECLARE
C_EMP SYS_REFCURSOR;
BEGIN
GET_EMPLOYEES('US', C_EMP);
END;
以下内容将失败:
DECLARE
C_EMP SYS_REFCURSOR;
L_REC C_EMP%ROWTYPE; --THIS LINE FAILS.
BEGIN
GET_EMPLOYEES('US', C_EMP);
-- LOOP AND FETCH GOES HERE.
END;
错误消息显示:
PLS-00320:此表达式类型的声明是 不完整或畸形
我不明白。我一直在其他一些匿名PL / SQL块中这样做,它完美地工作。这条线路有什么问题?无法弄清楚。
答案 0 :(得分:2)
我认为你误解了%ROWTYPE的使用。在存储表中的所有行时,应该只使用%ROWTYPE。而不是使用%ROWTYPE,使您自己的类型(记录)适合您要获取的列的数据类型。试试这个:
DECLARE
C_EMP SYS_REFCURSOR;
TYPE new_type IS RECORD(FIRST_NAME VARCHAR2(100), LAST_NAME VARCHAR2(200), DEPARTMENT_ID NUMBER, DEPARTMENT_NAME VARCHAR2(200), CITY VARCHAR2(200), STATE_PROVINCE VARCHAR2(200));
L_REC new_type; --instead of using %ROWTYPE, use the declared type
BEGIN
GET_EMPLOYEES('US', C_EMP);
LOOP
FETCH c_emp INTO l_rec;
EXIT WHEN c_emp%NOTFOUND;
dbms_output.put_line(l_rec.first_name||'_'||
l_rec.last_name||'_'||
l_rec.department_id||'_'||
l_rec.department_name||'_'||
l_rec.city||'_'||
l_rec.state_province);
END LOOP;
CLOSE c_emp;
END;
答案 1 :(得分:1)
我确信这个问题没有简短的答案。
要了解问题所在,您应该调查强类型和弱类型的反馈器是什么。
Oracle DBMS没有内置工具将refcursor结果放入网格中。如果您要编写一个尝试DBMS_SQL包和动态PL / SQL - 那么就可以编写一个产生您期望的结果的程序(即将任何sys_refcursor放入网格中)。
但是如果你刚开始学习PL / SQL,请不要浪费你的时间 - 首先,获得一些经验,你会看到如何做到这一点。只要没有发生,请使用SQL Developer的hack。