如何在匿名 PL/SQL 块中执行带有 out 游标参数的 oracle 过程?
How to execute an oracle procedure with an out cursor parameter in an anonymous PL/SQL block?
我正在学习 PL/SQL 使用 Oracle XE 的 HR 数据库。
我创建了以下存储过程:
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 开发人员 GUI 界面中执行它并查看结果。我还从 Justin Cave at here and 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: the declaration of the type of this expression is
incomplete or malformed
我不明白。我一直在其他几个匿名 PL/SQL 块中这样做,并且效果很好。那条线在这里有什么问题?想不通。
我认为您误解了 %ROWTYPE 的用法。当您存储 table 中的所有行时,您应该只使用 %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;
我确定这个问题没有简短的答案。
要了解问题所在,您应该调查什么是强类型和弱类型引用。
Oracle DBMS 没有将 refcursor 结果放入网格的内置工具。如果你打算写一个尝试 DBMS_SQL 包和动态 PL/SQL - 绝对有可能编写一个产生你期望结果的程序(即将任何 sys_refcursor 放入网格)。
但是如果你刚刚开始学习PL/SQL,请不要现在浪费你的时间 - 首先,获得一些经验,然后你就会知道如何去做。只要它没有发生,就使用 SQL 开发者的 hack.
我正在学习 PL/SQL 使用 Oracle XE 的 HR 数据库。
我创建了以下存储过程:
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 开发人员 GUI 界面中执行它并查看结果。我还从 Justin Cave at here and 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: the declaration of the type of this expression is incomplete or malformed
我不明白。我一直在其他几个匿名 PL/SQL 块中这样做,并且效果很好。那条线在这里有什么问题?想不通。
我认为您误解了 %ROWTYPE 的用法。当您存储 table 中的所有行时,您应该只使用 %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;
我确定这个问题没有简短的答案。
要了解问题所在,您应该调查什么是强类型和弱类型引用。
Oracle DBMS 没有将 refcursor 结果放入网格的内置工具。如果你打算写一个尝试 DBMS_SQL 包和动态 PL/SQL - 绝对有可能编写一个产生你期望结果的程序(即将任何 sys_refcursor 放入网格)。
但是如果你刚刚开始学习PL/SQL,请不要现在浪费你的时间 - 首先,获得一些经验,然后你就会知道如何去做。只要它没有发生,就使用 SQL 开发者的 hack.