【问题标题】:How should I temporarily store data within a PL/SQL procedure?我应该如何在 PL/SQL 过程中临时存储数据?
【发布时间】:2016-09-02 08:59:47
【问题描述】:

我对 PL/SQL 很陌生。我在一个名为“FLEX_PANEL_INSPECTIONS”的初始表中有数据,我试图使用 PL/SQL 过程在名为“PANEL_STATUS_2”的第二个表中进行汇总。然而,由于数据的性质,我不得不写一个case语句来正确地总结来自FLEX_PANEL_INSPECTIONS的数据。因此,我创建了第三个中间表来连接两者(名为“PANEL_STATUS_1”),因为 case 语句不允许 group by 子句中专门对数据进行排序的列(据我所知 - 当我尝试这样做)。我不想将数据存储在中间表中 - 有什么方法可以使其成为临时表(即仅在过程运行时存在,以便不保留来自“PANEL_STATUS_1”的数据);在过程中创建视图,还是完全不需要中间表?

对我对 PL/SQL 的错误/误解的任何帮助或批评将不胜感激。这是我写的代码:

create or replace procedure PANEL_STATUS_PROCEDURE (panel_lot_id in number) as

begin

--Populate intermediate table with information about the status of the panels.
insert into PANEL_STATUS_1 (FLEX_LOT_ID, FLEX_PANEL_DMX, FLEX_PANEL_STATUS)   
select FLEX_LOT_ID, FLEX_PANEL_DMX,

--Sum the status values of the 4 panel inspections. A panel passes if and only if this sum = 4. 
case sum (FLEX_PANEL_STATUS)
    when 4 then 1
    else 0

end as new_panel_status

from FLEX_PANEL_INSPECTIONS
where FLEX_LOT_ID = panel_lot_id
group by FLEX_LOT_ID, FLEX_PANEL_DMX;

--Add information about the machine ID and the upload time to this table.
insert into PANEL_STATUS_2 (FLEX_LOT_ID, FLEX_PANEL_DMX, FLEX_PANEL_STATUS, MACHINE_ID, UPLOAD_TIME)
select distinct PANEL_STATUS_1.*, MACHINE_ID, UPLOAD_TIME
from PANEL_STATUS_1, FLEX_PANEL_INSPECTIONS

where (FLEX_PANEL_INSPECTIONS.FLEX_LOT_ID = PANEL_STATUS_1.FLEX_LOT_ID
       and FLEX_PANEL_INSPECTIONS.FLEX_PANEL_DMX = PANEL_STATUS_1.FLEX_PANEL_DMX)

and FLEX_PANEL_INSPECTIONS.FLEX_LOT_ID = panel_lot_id;

end PANEL_STATUS_PROCEDURE;
/

【问题讨论】:

    标签: sql oracle plsql temporary


    【解决方案1】:

    您可以将临时表创建为

    create global temporary table gtt_panel_status
    ( column datatype ... )
    on commit [delete|preserve] rows;
    

    (在on commit 子句中指定deletepreserve)。

    但是,您通常不需要临时表。您可以尝试使用with 子句(CTE),或者沿select x, y, z from (select your subquery here) 行的内联视图。

    编辑:实际上查看您的查询更多,我认为您真正需要的是分析sum,即没有汇总的总数。例如,像这样:

    create or replace procedure panel_status_procedure
        ( panel_lot_id in number )
    as
    begin
        -- Add information about the machine ID and the upload time to this table.
        insert into panel_status_2
             ( flex_lot_id
             , flex_panel_dmx
             , flex_panel_status
             , machine_id
             , upload_time )
        select distinct
               flex_lot_id
             , flex_panel_dmx
             , case sum(flex_panel_status) over (partition by flex_lot_id, flex_panel_dmx)
                   when 4 then 1
                   else 0
               end
             , machine_id
             , upload_time
        from   flex_panel_inspections pi
        where  pi.flex_lot_id = panel_lot_id;
    
    end panel_status_procedure;
    

    【讨论】:

    • 谢谢,这回答了我的问题。 commit 子句会在什么时候删除行?
    • 如果表定义为on commit delete rows,则commit清除数据。即它仅在交易期间持续。如果是on delete preserve rows,那么它会在会话期间持续。
    • 重新编辑您的编辑-我认为您误解了代码的要点-我对面板进行了几次检查,结果是布尔通过或失败(1 或 0)。仅当所有检查均以 1 的值通过时,面板的状态才被指定为 1 值;否则状态被赋值为 0。因此我需要代码块中的 case 语句:)
    • 你是对的,case 表达式在复制和粘贴中丢失了。更新了 - 更好了吗?
    • group by 聚合整个结果集(类似于distinct)。以over () 开头的窗口子句使其成为analytic function,它计算指定窗口的单个值而不聚合结果集。这意味着您仍然可以从 flex_panel_inspections 中获取所有原始行,但每行都有一个额外的计算值。
    猜你喜欢
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多