可以像表一样更新oracle类型吗?

时间:2010-06-14 16:27:54

标签: oracle plsql

我正在将GTT转换为oracle类型,如APC的优秀answer所述。但是,某些GTT正在根据另一个表中的选择查询进行更新。例如:

UPDATE my_gtt_1 c
   SET (street, city, STATE, zip) = (SELECT src.unit_address,
                                            src.unit_city,
                                            src.unit_state,
                                            src.unit_zip_code
                                       FROM (SELECT mbr.ROWID row_id,
                                                    unit_address,
                                                    RTRIM(a.unit_city) unit_city,
                                                    RTRIM(a.unit_state) unit_state,
                                                    RTRIM(a.unit_zip_code) unit_zip_code
                                               FROM table_1        b,
                                                    table_2          a,
                                                    my_gtt_1 mbr
                                              WHERE type = 'ABC'
                                                AND id = b.ssn_head
                                                AND a.h_id = b.h_id
                                                AND row_id >= v_start_row
                                                AND row_id <= v_end_row) src
                                      WHERE c.ROWID = src.row_id)
 WHERE state IS NULL
    OR state = ' ';

如果my_gtt_1不是全局临时表而是oracle集合类型,那么是否可以对此复杂进行更新?或者在这些情况下,我们最好使用全局临时表?

2 个答案:

答案 0 :(得分:1)

我认为APC answer to your previous question的这一部分与此相关:

  

全球临时表也很好   如果我们有很多中间人   处理也是如此   单一的解决很复杂   SQL查询。特别是如果那样   处理必须应用于子集   检索到的行。

您无法像使用GTT一样使用UPDATE语句更新内存数据;你需要编写程序代码来定位和更改有问题的数组元素。

答案 1 :(得分:1)

您无法对对象类型执行set UPDATE操作。您必须逐行执行此操作,如:

FOR i IN l_tab.FIRST..l_tab.LAST LOOP
   SELECT src.unit_address,
          src.unit_city,
          src.unit_state,
          src.unit_zip_code
     INTO l_tab(i).street, 
          l_tab(i).city,  
          l_tab(i).STATE,  
          l_tab(i).zip
     FROM (your_query) src;
 END LOOP;

因此,您应该尝试在创建时进行所有计算(可以进行BULK COLLECT)。显然,如果您的进程需要许多步骤,您可能会发现全局临时表的性能优于内存中结构。


从您提出的最后一个问题来看,您似乎正在尝试用对象表替换所有全局临时表。我建议谨慎,因为一般来说,它们不可互换:

  • 对象表是内存中的结构:您不希望将百万+行表加载到内存中。它们主要用作缓冲区:您将一些(例如100个)行加载到结构中,执行您需要对这些行执行的操作,然后加载下一批。您不能轻易地将此结构视为常规表:例如,您只能使用标准索引键有效地搜索此结构(除非您将结构定义为由rowid索引,否则不能通过示例中的rowid进行搜索)。
  • 另一方面,临时表与普通表非常相似。您可以在其中加载数百万行,执行连接,复杂的集合操作。您可以索引临时表以进一步优化。

在我看来,您正在尝试进行的更改将对您的逻辑进行大规模改革,并且可能效果不佳。通常,您不会将GTT替换为对象表。您可以通过直接使用SET操作来删除性能显着提升的GTT(对您的数据执行大量的UPDATE / DELETE / INSERT 直接而不使用临时表)。

我建议在选择解决方案之前执行基准测试(这可能就是你现在正在做的事情:)