Oracle 将REF游标返回到过程生成的数据

Oracle 将REF游标返回到过程生成的数据,oracle,stored-procedures,plsql,Oracle,Stored Procedures,Plsql,我需要编写一个存储过程,在表上执行一些插入操作,并根据插入操作的进展情况为每一行编译一个“状态”列表。每一行都将被插入到一个循环中,循环在为INSERT语句提供一些值的游标上迭代。我需要返回的结果集如下所示: FIELDS_FROM_ROW_BEING_INSERTED.., STATUS VARCHAR2 状态由插入的方式决定。例如,如果INSERT导致DUP_VAL_ON_索引异常,表明存在重复的行,我会将状态设置为“Dupe”。如果一切顺利,我会将其设置为“成功”,然后继续下一行 最后,

我需要编写一个存储过程,在表上执行一些插入操作,并根据插入操作的进展情况为每一行编译一个“状态”列表。每一行都将被插入到一个循环中,循环在为INSERT语句提供一些值的游标上迭代。我需要返回的结果集如下所示:

FIELDS_FROM_ROW_BEING_INSERTED.., STATUS VARCHAR2
状态由插入的方式决定。例如,如果INSERT导致DUP_VAL_ON_索引异常,表明存在重复的行,我会将状态设置为“Dupe”。如果一切顺利,我会将其设置为“成功”,然后继续下一行

最后,我将得到一个由N行组成的结果集,其中N是执行的insert语句的数量,每行包含一些被插入行的标识信息,以及插入的“状态”

由于我的数据库中没有表来存储我想传递给用户的值,我想知道如何返回信息?临时桌子?似乎在Oracle中,临时表是“全局的”,我不确定是否需要一个全局表,是否有任何临时表在会话完成后被删除?

“全局”在临时表的情况下,只是表示它们是永久的,数据是临时的

我将定义一个与光标匹配的记录类型,以及状态字段。然后定义该类型的表

TYPE t_record IS
(
    field_1,
    ...
    field_n,
    status VARCHAR2(30)
);

TYPE t_table IS TABLE OF t_record;

FUNCTION insert_records
(
    p_rows_to_insert IN SYS_REFCURSOR
)
    RETURN t_table;
更好的做法是将输入定义为表类型而不是游标。

“全局”在临时表的情况下意味着它们是永久的,而数据是临时的

我将定义一个与光标匹配的记录类型,以及状态字段。然后定义该类型的表

TYPE t_record IS
(
    field_1,
    ...
    field_n,
    status VARCHAR2(30)
);

TYPE t_table IS TABLE OF t_record;

FUNCTION insert_records
(
    p_rows_to_insert IN SYS_REFCURSOR
)
    RETURN t_table;

更好的做法是将输入定义为表类型而不是游标。

如果您使用的是Oracle 10gR2或更高版本,那么您应该查看DML错误日志。这基本上实现了您想要实现的目标,也就是说,它允许我们通过记录任何错误并继续执行语句来执行批处理过程中的所有DML

其原理是,我们使用PL/SQL内置包DBMS_ERRLOG为需要处理的每个表创建一个错误日志表。DML语法有一个简单的扩展,可以将消息记录到错误日志表中。这种方法不会创建比您的方案更多的对象,并且具有使用一些标准Oracle功能的优点


在处理大容量处理时(即使用FORALL语法时),我们可以使用内置的SQL%bulk_exceptions集合捕获异常。可以将批量异常与DML错误日志记录相结合,但这可能会在11g中产生问题

如果您使用的是Oracle 10gR2或更高版本,则应查看DML错误日志。这基本上实现了您想要实现的目标,也就是说,它允许我们通过记录任何错误并继续执行语句来执行批处理过程中的所有DML

其原理是,我们使用PL/SQL内置包DBMS_ERRLOG为需要处理的每个表创建一个错误日志表。DML语法有一个简单的扩展,可以将消息记录到错误日志表中。这种方法不会创建比您的方案更多的对象,并且具有使用一些标准Oracle功能的优点


在处理大容量处理时(即使用FORALL语法时),我们可以使用内置的SQL%bulk_exceptions集合捕获异常。可以将批量异常与DML错误日志记录相结合,但这可能会在11g中产生问题

全局临时表在会话完成后(或在提交后,具体取决于您如何设置)删除数据,但结构保持永久性,以便您可以针对它们编译代码等。但是,没有两个会话可以看到彼此的数据。@kurosch因此在我的存储过程中,我必须检查临时表是否已经存在,如果不是,我会创造它吗?我希望我可以使用Sybase语法INSERT-INTO#mytemp。。。然后我就不必担心表名冲突了。不,表本身是模式的永久部分,就像其他永久表一样创建。您给它一个常规名称,并像其他表一样引用它。唯一的区别是数据只存在于会话中(它使用SGA或类似的东西)。全局临时表在会话完成后(或提交后,取决于您如何设置它们)删除数据,但结构保持永久性,以便您可以针对它们编译代码,等等。没有两个会话可以看到彼此的数据,但是。@kurosch所以在我的存储过程中,我必须检查临时表是否已经存在,如果不存在,我会创建它吗?我希望我可以使用Sybase语法INSERT-INTO#mytemp。。。然后我就不必担心表名冲突了。不,表本身是模式的永久部分,就像其他永久表一样创建。您给它一个常规名称,并像其他表一样引用它。唯一的区别是数据只存在于会话中(它使用SGA或类似的东西)。我的面向客户端的应用程序需要状态信息,因此存储过程需要将其作为结果返回我的面向客户端的应用程序需要状态信息,因此存储过程需要将其作为结果集返回