sql - ORA-08103 在过程中使用全局临时表 DML(插入、更新、选择),选择光标到临时表显示错误对象不存在

标签 sql oracle stored-procedures cursor temp-tables

基本上我需要修改数据并将其存储在临时表中,每次在暴露数据后执行过程时删除数据。问题是作为过程结果在游标中使用的临时表显示错误

object doesn't exist

我正在尝试使用存储过程从全局临时表中获取数据,然后截断存储过程中的数据。我从 Oracle 数据库收到“不再存在”错误,我尝试了 3 种不同的方法:

  1. 带有 ON COMMIT DELETE ROWS; 语句和过程末尾的 COMMIT; 的临时表。

  2. 带有 ON COMMIT PRESERVE ROWS; 语句和过程末尾的 TRUNCATE TABLE 的临时表

  3. 过程末尾带有 EXECUTE IMMEDIATE 'TRUNCATE TABLE TABLE_NAME' 语句的常规表

所有这些选项都显示相同的错误。

我有 2 个表,我正在将这 2 个表合并到全局临时表中,更改记录的某些值。

然后我创建一个游标以将 SELECT 返回到临时表。

错误出现时就是在这里。

因此,我创建了下表:

CREATE GLOBAL TEMPORARY TABLE REM_ORDENSECCIONES_TPM (
    SE_CONSEC   NUMBER(38,0),
    SE_NOMBRE   VARCHAR2(250 BYTE),
    ET_CONSEC   NUMBER(38,0),
    SE_ORDENS   NUMBER(38,0),
    DI_CONSEC   NUMBER(38,0)
)
ON COMMIT DELETE ROWS;
--
CREATE GLOBAL TEMPORARY TABLE REM_ORDENSECCIONES (
    SE_CONSEC   NUMBER(38,0),
    SE_NOMBRE   VARCHAR2(250 BYTE),
    ET_CONSEC   NUMBER(38,0),
    SE_ORDENS   NUMBER(38,0),
    DI_CONSEC   NUMBER(38,0)
)
ON COMMIT PRESERVE ROWS;
--
CREATE TABLE REM_ORDENSECCIONESP (
    SE_CONSEC   NUMBER(38,0),
    SE_NOMBRE   VARCHAR2(250 BYTE),
    ET_CONSEC   NUMBER(38,0),
    SE_ORDENS   NUMBER(38,0),
    DI_CONSEC   NUMBER(38,0)
)

我有这个存储过程:

CREATE OR REPLACE PROCEDURE SP_OBTENER_SECCION_AMBULATORIO(etConsec NUMBER DEFAULT NULL,
                                                    diConsec NUMBER DEFAULT NULL,
                                                    cursorParam OUT SYS_REFCURSOR)
AS
BEGIN
    --
    -- SE TRAEN TODAS LAS SECCIONES QUE ESTÁN EN PREGEVEN Y LAS QUE COINCIDAN
    -- CON LA ETAPA Y EL DIAGNÓSTICO EN SECCPREG
    -- SE GUARDAN EN LA TABLA TEMPORAL PARA PODER MODIFICAR EL ORDEN MÁS ADELANTE.

    --DEBUG
    -- SELECT * FROM REM_ORDENSECCIONES_TPM;
    -- SELECT * FROM REM_SECCPREG WHERE SE_CONSEC = 217;
    -- UPDATE REM_PREGEVEN SET SE_ORDEN = 11 WHERE SE_CONSEC = 217;
    INSERT INTO REM_ORDENSECCIONESP (SE_CONSEC, SE_NOMBRE, ET_CONSEC, SE_ORDENS)
        SELECT SE_CONSEC, SE_NOMBRE, ET_CONSEC, SE_ORDENS
        FROM REM_SECCPREG  
        WHERE SE_CONSEC IN 
                        (SELECT DISTINCT SE_CONSEC
                         FROM REM_PREGEVEN 
                         WHERE ET_CONSEC = etConsec AND DI_CONSEC = diConsec AND PR_ESTADO <> 'I') 
        OR ET_CONSEC = etConsec and Di_Consec = diConsec
        ORDER BY SE_ORDENS;
    --        
    -- ACTUALIZA LA TABLA TEMPORAL DE LAS SECCIONES CON EL SE_ORDEN
    -- DE LA TABLA DE REM_PREGEVEN.
    --

    --DEBUG
    -- SELECT * FROM REM_ORDENSECCIONES_TPM;
    -- COMMIT;
    UPDATE REM_ORDENSECCIONESP TMP
        SET TMP.SE_ORDENS = (SELECT DISTINCT PREGE.SE_ORDEN 
                             FROM REM_PREGEVEN PREGE 
                             WHERE ET_CONSEC = etConsec AND DI_CONSEC = diConsec AND PR_ESTADO <> 'I'
                             AND TMP.SE_CONSEC = PREGE.SE_CONSEC)
    WHERE EXISTS (SELECT 1
                    FROM REM_PREGEVEN PREGE
                    WHERE TMP.SE_CONSEC = PREGE.SE_CONSEC AND SE_ORDEN IS NOT NULL);

 OPEN cursorParam FOR 
  SELECT SE_CONSEC, SE_NOMBRE, ET_CONSEC FROM REM_ORDENSECCIONESP;
--COMMIT; --COMMIT NECESARIO PARA ELIMINAR LOS DATOS TEMPORALES


  EXECUTE IMMEDIATE 'TRUNCATE TABLE REM_ORDENSECCIONESP';-- || TBL_NAME;
END;

有什么建议吗?我没有更多的路径可以尝试。

我不是 Oracle 专家,我在 SQL Server 中使用了临时表,一切都很好。

谢谢! :)

最佳答案

SQL Server 中的临时表与 Oracle 中的全局临时表不同。具体来说,全局临时表是永久数据结构,它只是临时数据。 GTT 中的数据仅限于插入它的 session ,并且将在事务或 session 结束时被删除,具体取决于表的定义方式。

关于您的过程的另一件事是它将打开的引用游标传递给调用程序。游标不是数据集,它是指向查询的指针:调用程序随后获取数据,这意味着它执行查询并处理其结果集。问题是,在打开查询后,您的过程立即执行EXECUTE IMMEDIATE 'TRUNCATE TABLE REM_ORDENSECCIONESP';。因此,当调用程序尝试从光标获取记录时,橱柜是空的。

删除截断表语句。它正在破坏你的流程。 GTT 的问题之一是发出 DDL 比普通表更麻烦:例如,如果有任何使用过 GTT 的 session 仍处于打开状态,我们就无法删除 GTT。幸运的是,鉴于全局临时表的行为,截断几乎肯定是不必要的。如果您确实认为需要某些东西,只需在流程开始时从 GTT 中删除即可;这将在您重新填充之前清除 session 早期(事务?)的任何残留数据。

这是 db<>fiddle 上的演示.

关于sql - ORA-08103 在过程中使用全局临时表 DML(插入、更新、选择),选择光标到临时表显示错误对象不存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57227294/

相关文章:

c# - 在 Nhibernate QueryOver 中使用计算属性(未映射)

mysql - SQL 选择并查找其他表中不存在的行

MySQL 在年中的第几天和年中选择记录

oracle - 如何在 perl 脚本中使用 IPC::Run 模块

sql - 如何通过省略组内的值来减少数据集

MySQL-列中值的所有子集

mysql - phpmyadmin wamp mysql 无法在过程中声明变量

sql - 大多数执行的存储过程?

sql - 通用递归sql查询

php - 从 PHP 脚本调用 mySQL 存储过程 - 没有错误但不执行?