如何在Oracle数据库中的pl / sql过程中存储值

时间:2015-07-16 14:44:01

标签: oracle plsql

我想在循环迭代后将select查询中的值添加到某个变量/属性。像Java中的Arraylist这样的价值持有者。

循环终止后,我需要删除变量/属性中的值。

如何在pl / sql编程中实现这一点。

     FOR FEH IN (SELECT ID FROM T_FEH_SG WHERE ZESG_ID IS NOT NULL) LOOP 
     FOR UWBFEH IN (SELECT * FROM T_GRPN_J_FERF WHERE FEH_ID = FEH.ID) LOOP 

     // Here some code to add values from select query based on some conditions


     END LOOP;
      // Here I need to delete the added values.
     END LOOP;

如果我删除存储的值,那么也应该从实际表中删除这些值。

2 个答案:

答案 0 :(得分:1)

我通常建议不要使用嵌套循环,而是使用连接。 在您的示例中,它看起来有点像您希望使用关联数组并使用批量收集填充它:

...
TYPE T_myTable IS TABLE OF T_UWB_GRUPPEN_J_FEHLERF%ROWTYPE INDEX BY PLS_INTEGER;
myTable T_myTable;
...
FOR FEH IN (SELECT ID FROM T_FEHLERFALL_SG WHERE ZESG_ID IS NOT NULL) LOOP
   -- select into table
   SELECT * BULK COLLECT INTO myTable FROM T_UWB_GRUPPEN_J_FEHLERF WHERE FEHLERF_ID = FEH.ID;
   ...
   -- delete table
   myTable.DELETE;
END LOOP;
...

答案 1 :(得分:1)

由于您实际上不需要来自T_FEHLERFALL_SG表的任何数据,您可以摆脱第一个循环进行单个SELECT(使用JOIN,EXISTS或IN,具体取决于您要获取的数据)。

还有一个重要的问题需要回答 - 在将数据插入数组之前是否需要执行任何逻辑?在清除之前,您打算如何处理存储在数组中的值?

无论如何,这里有一些你可能会觉得有用的选项(同样,我使用了声明的CURSOR,因为它提供了更好的代码可读性,据我所知,它更好地由优化器管理,可以快速重用获取结果来自SGA - 您还可以阅读Result cacheOracle Concepts - SGA)。

DECLARE
    TYPE t_uwbfeh_tab IS TABLE OF T_UWB_GRUPPEN_J_FEHLERF%ROWTYPE INDEX BY PLS_INTEGER; -- empirically learned (and from our DB Oracle consultant) arrays indexed by PL/SQL types (especially PLS_INTEGER) react noticeably faster even for a ~1k-element arrays
    -- declare the PL/SQL TABLE variable and initialize it
    l_uwbfeh_arr t_uwbfeh_tab := NEW t_uwbfeh_tab();

    CURSOR c_fetch_data
    SELECT
        UWBFEH.*
    FROM
        T_FEHLERFALL_SG FEH
        ,T_UWB_GRUPPEN_J_FEHLERF UWBFEH
    WHERE
        FEH.ZESG_ID IS NOT NULL
        AND FEH.ID = UWBFEH.FEHLERF_ID;

BEGIN
    -- If you don't need to do anything with the data in the array before inserting it into the array
    OPEN c_fetch_data;
    FETCH c_fetch_data BULK COLLECT INTO l_uwbfeh_arr;
    CLOSE c_fetch_data;

    -- If you really need to do some logic not doable with the 'smart' select statement
    FOR UWBFEH IN c_fetch_data
    LOOP
        -- extend an array - let it store one more value
        l_uwbfeh_arr.EXTEND;

        -- do some logic with your values (here I just print out the FEHLERF_ID)
        DBMS_OUTPUT.PUT_LINE('FEHLERF_ID: ' || UWBFEH.FEHLERF_ID);

        -- insert the value into the array
        l_uwbfeh_arr(l_uwbfeh_arr.LAST) := UWBFEH;
    END LOOP;

    -- If you need to do something with the data fetched in the array
    IF l_uwbfeh_arr.COUNT > 0 THEN
        FOR idx IN l_uwbfeh_arr.FIRST .. l_uwbfeh_arr.LAST
        LOOP
            -- access the rows as follows (here I just print out the FEHLERF_ID)
            DBMS_OUTPUT.PUT_LINE('FEHLERF_ID: ' || l_uwbfeh_arr(idx).FEHLERF_ID);
        END LOOP;
    END IF;

    -- If you don't actually need any data to be stored in the array and need to manipulate only on the fetched rows
    -- you could skip fetching the data into the array and execute the logic in the following loop
    FOR UWBFEH IN c_fetch_data
    LOOP
        -- here do the logic (here I just print out the FEHLERF_ID)
        DBMS_OUTPUT.PUT_LINE('FEHLERF_ID: ' || UWBFEH.FEHLERF_ID);
    END LOOP;

    -- to delete all the data stored in the array, simply use the following line of code
    l_uwbfeh_arr.DELETE;
END;
/