Oracle Хранимая процедура - Могу ли я очистить временную таблицу после создания курсора - PullRequest
0 голосов
/ 27 января 2020

У меня есть API веб-службы, который использует список идентификатора элемента в качестве входного параметра и таблицу данных в качестве выходного параметра (среди других параметров, не имеющих отношения к этому вопросу). Этот API вызывает хранимую процедуру Oracle в пакете, чтобы получить содержимое таблицы выходных данных.

Хранимая процедура проходит по каждому идентификатору элемента и определяет результат для него. Затем он использует временную таблицу для хранения результатов для каждого идентификатора элемента (идентификатор элемента, результат, sysdate). Наконец, курсор используется для запроса этой временной таблицы и получения результата.

Мой вопрос заключается в том, что со временем содержимое этой таблицы данных становится слишком большим (миллионы записей). Я знаю, что у меня может быть процесс очистки, но мне было интересно, допустимо ли удалять содержимое после создания курсора.

Это политическая версия API веб-службы и хранимая процедура:

public static EnumGlobal.Errorcode GetOutcomeByItem(string itemIDs, out DataTable dtOutcome, ...)
{
    OracleDbContext dbContext = new OracleDbContext();
    List<OracleParameter> spParams = new List<OracleParameter>();
    DataSet dsOutcome = new DataSet();
    ...
    try
    {
        spParams.Add(new OracleParameter("IPSITEMIDS", OracleDbType.Varchar2, itemIDs, ParameterDirection.Input));
        ...
        spParams.Add(new OracleParameter("CUR_OUT", OracleDbType.RefCursor, ParameterDirection.Output));

        try
        {
            dbContext.Open();
            dbContext.ExecuteStoredProcedure("PKGSOMEQUERY.USPGETOUTCOMEBYITEM", spParams, ref dsOutcome);
        }
    }
}

PROCEDURE USPGETOUTCOMEBYITEM
(
IPSITEMIDS                VARCHAR2,
...
CUR_OUT                   OUT GETDATACURSOR
)
IS
LVSQUERY                VARCHAR2(4000):='';
V_OUTCOME VARCHAR2(5);
V_NEWITEMSLIST VARCHAR2(4000) := REPLACE(IPSITEMIDS, '''', '');

CURSOR cur IS
SELECT  REGEXP_SUBSTR(V_NEWITEMSLIST, '[^,]+', 1, LEVEL) V_NEWITEM2 FROM DUAL CONNECT BY instr(V_NEWITEMSLIST, ',',1, LEVEL -1) > 0;

BEGIN
-- Loop thorugh each ITEM ID and determine outcome, add ITEM ID and OUTCOME to temp table
FOR rec IN cur LOOP   
    V_NEWITEM := rec.V_NEWITEM2;
    ...
    -- Determine V_OUTCOME
    ...
    INSERT INTO TEMPOUTCOME
    (
      ITEMID,
      OUTCOME,
      ORIGINDATE
    )
    VALUES
    (
        V_NEWITEM,
        V_OUTCOME,
        SYSDATE
    );
    COMMIT;
END LOOP;

LVSQUERY:='SELECT ITEMID, OUTCOME, ORIGINDATE FROM TEMPOUTCOME WHERE ITEMID IN (' || IPSITEMIDS || ')';

OPEN CUR_OUT FOR LVSQUERY;
COMMIT;

-- Can I do this?
-- Delete from temp table all item IDs used in this session, in one shot
--    DELETE FROM TEMPOUTCOME WHERE ITEMID IN (select REGEXP_SUBSTR(IPSITEMIDS, '\''(.*?)\''(?:\,)?', 1, LEVEL, NULL, 1) FROM dual CONNECT BY LEVEL <= REGEXP_COUNT(IPSITEMIDS, '''(?: +)?(\,)(?: +)?''', 1) + 1);        

EXCEPTION WHEN OTHERS THEN
    PKGHANDLEERROR.USPHANDLEERROR('USPGETOUTCOMEBYITEM', LVIERRORCODE);
    OPIERRORCODE:=LVIERRORCODE;
END USPGETOUTCOMEBYITEM;

1 Ответ

0 голосов
/ 30 января 2020

Я на самом деле не проверял это, но с точки зрения общих знаний ORACLE, как только вы открываете курсор, вы больше не имеете дело с сохраненными данными. Вместо этого вы выполняете итерацию снимка в памяти. Поэтому я считаю, что это должно работать. Если нет огромного количества данных и oracle пытается отобразить результаты (не уверен, действительно ли это происходит, хотя) ...

В качестве простого / безопасного варианта вы можете удалить записи за день / час / минута (в зависимости от использования).

Также в качестве предложения, если вы один раз вставили sysdate в переменную и используете его во вставке, вам может быть намного легче иметь дело с набором данных. как вы можете просто запросить по происхождению. Это также ускорит вставку

Еще одна вещь, на которую стоит взглянуть (возможно, даже лучшая), это Oracle Временные таблицы.

...