Выберите из таблицы, которая может не существовать - PullRequest
0 голосов
/ 27 апреля 2018

У нас есть проблема, для обхода которой нужен неудачный взлом. Позвольте мне дать вам некоторый контекст:

У нас есть приложение, которое переопределяет параметры конфигурации клиентов при его удалении / переустановке. Он устанавливается со значениями по умолчанию, переопределяя любые настройки, введенные пользователем.

Решением руководства было бы создать два сценария, по одному для каждого шага:

  1. Создайте временную таблицу и скопируйте в нее параметры конфигурации перед удалением приложения.

  2. После переустановки приложения скопируйте значения из временной таблицы обратно в исходную таблицу, чтобы сохранить их настройки.

Мне не очень нравится их решение, но я должен пойти с ним.

У меня шаг 1 вниз, но у меня возникают проблемы с запуском второго скрипта (шаг 2) без запуска первого скрипта (шаг 1).

По сути, временной таблицы не будет, когда компилируется второй скрипт, если кто-то в другом отделе забудет запустить первый.

Это код, который я сейчас использую для второго скрипта.

DECLARE
    lvnTableExists              NUMBER(1);
    lvbTempTableCopied          BOOLEAN;
    lvsTempTable                VARCHAR2(21) := 'TEMP_TABLE';
BEGIN
    -- CalcTypVarValue Table Copy
    SELECT COUNT(*)
    INTO   lvnTableExists
    FROM   ALL_TABLES x
    WHERE  x.Table_Name = lvsTempTable ;

    IF lvnTableExists = 1 THEN
        FOR CalcRow IN (SELECT * FROM Temp_Table) LOOP -- Temp_Table will not exist if first script didn't run, causing a compile error
            UPDATE SomeOtherTable c
            SET    c.foo= CalcRow.foo,
                   c.bar= CalcRow.bar,
                   c.DateLastMaint = SYSDATE
            WHERE  c.bob= CalcRow.bob
            AND    c.bill= CalcRow .bill;
        END LOOP;
        lvbTempTableCopied    := TRUE;
    ELSE
        lvbTempTableCopied    := FALSE;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
    ...
    ...

Моя проблема в том, что если Temp_Table вообще не существует, то я получу ошибку во время компиляции, поэтому скрипт вообще не запустится. Мне нужно, чтобы он работал, чтобы я мог принять решение о том, нужно ли делать что-то еще, если таблица не существует на основе lvbTempTableCopied.

Я слышал об обходе с чем-то вроде FOR CalcRow IN (EXECUTE IMMEDIATE 'SELECT * FROM ' || lvsTempTable), но я не могу использовать его в FOR IN LOOP как этот.

Как бы я использовал EXECUTE IMMEDIATE, чтобы обойти ошибку времени компиляции?

1 Ответ

0 голосов
/ 28 апреля 2018

Вы можете сделать это динамически, используя REF CURSOR, см. Пример кода ниже,

DECLARE
    TYPE cur_typ IS REF CURSOR;
    c cur_typ;
    v_table_exists VARCHAR2(1);
    type temp1_rec is record (col1 VARCHAR2(100), col2 VARCHAR2(100));
    v_temp temp1_rec;
BEGIN
    SELECT 'Y'
      INTO v_table_exists
      FROM all_tables
     WHERE table_name = 'TEMP1';

     --dynamic query with parameters
     OPEN c FOR 'SELECT col1, col2 FROM temp1 WHERE :param1=:param2' USING 'PARAM1', 'PARAM1' ;
     LOOP
         FETCH c INTO v_temp;
         EXIT WHEN c%NOTFOUND;
         DBMS_OUTPUT.PUT_LINE(v_temp.col1);
     END LOOP;  
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        NULL;
END;
/

CREATE TABLE TEMP1
(COL1 VARCHAR2(100),
 col2 VARCHAR2(100));

INSERT INTO temp1
VALUES('123123123asdfasdfsfa', 'JHASDKLFJLASDFLAS');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...