срок службы временной таблицы - PullRequest
9 голосов
/ 02 декабря 2009

У меня следующая процедура:

CREATE PROCEDURE foo ()
    SELECT * FROM fooBar INTO TEMP tempTable;

    -- do something with tempTable here

    DROP TABLE tempTable;
END PROCEDURE;

Что произойдет, если перед вызовом DROP TABLE возникнет исключение? Будет ли TempTable еще после выхода из foo?

Если это так, foo может потерпеть неудачу при следующем вызове, поскольку tempTable уже существует. Как это должно быть обработано.

РЕДАКТИРОВАТЬ: я использую informix 11,5

Ответы [ 5 ]

4 голосов
/ 03 декабря 2009

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

Если хранимая процедура завершается ошибкой из-за того, что таблица уже существует, SPL генерирует исключение. Вы можете иметь дело с исключениями, добавив предложение ON EXCEPTION - но вы вводите одну из более барочных частей SPL, язык хранимых процедур.

Вот слегка измененная версия вашей хранимой процедуры - та, которая генерирует исключение деления на ноль (SQL -1202):

CREATE PROCEDURE foo ()
    define i integer;
    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;
END PROCEDURE;

execute procedure foo();
SQL -1202: An attempt was made to divide by zero.

execute procedure foo();
SQL -958: Temp table temptable already exists in session.

Это показывает, что в первый раз через код выполнялся SELECT, создавая таблицу, а затем выполнялся фол деления на ноль. Во второй раз, однако, произошел сбой SELECT, поскольку временная таблица уже существует, отсюда и другое сообщение об ошибке.

drop procedure foo;
CREATE PROCEDURE foo()
    define i integer;

    BEGIN
        ON EXCEPTION
            DROP TABLE tempTable;
            SELECT * FROM 'informix'.systables INTO TEMP tempTable;
        END EXCEPTION WITH RESUME;
        SELECT * FROM 'informix'.systables INTO TEMP tempTable;
    END;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;
END PROCEDURE;

Блок BEGIN / END ограничивает обработку исключений оператором trapped. Без BEGIN / END обработка исключений охватывает всю процедуру, также реагируя на ошибку деления на ноль (и, следовательно, позволяя DROP TABLE работать и процедура, кажется, выполняется успешно).

Обратите внимание, что в этот момент все еще существует искушаемое:

+ execute procedure foo();
SQL -1202: An attempt was made to divide by zero.
+ execute procedure foo();
SQL -1202: An attempt was made to divide by zero.

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

Вы можете ограничить блок ON EXCEPTION выбранными кодами ошибок (-958 кажется вероятным для этого) с помощью:

ON EXCEPTION IN (-958) ...

См. Руководство IBM Informix по SQL: руководство по синтаксису, глава 3 «Операторы SPL».

Обратите внимание, что Informix 11.70 добавил операторы 'IF EXISTS' и 'IF NOT EXISTS' в операторы CREATE и DROP. Таким образом, вы можете использовать модифицированный оператор DROP TABLE :

DROP TABLE IF EXISTS tempTable;

Таким образом, в Informix 11.70 или более поздней версии проще всего написать процедуру:

DROP PROCEDURE IF EXISTS foo;

CREATE PROCEDURE foo()
    define i integer;
    DROP TABLE IF EXISTS tempTable;

    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;  -- Still a good idea
END PROCEDURE;

Вы также можете использовать это, но затем вы получите предыдущее определение процедуры, какой бы она ни была, и это может быть не то, что вы ожидали.

CREATE PROCEDURE IF NOT EXISTS foo()
    define i integer;
    DROP TABLE IF EXISTS tempTable;

    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;  -- Still a good idea
END PROCEDURE;
3 голосов
/ 03 декабря 2009

Я наконец-то использовал вариант решения Джонатана и RET:

CREATE PROCEDURE foo ()
    ON EXCEPTION IN (-206)
    END EXCEPTION WITH RESUME;

    DROP TABLE tempTable;    

    SELECT * FROM fooBar INTO TEMP tempTable;

    -- do something with tempTable here

    DROP TABLE tempTable;
END PROCEDURE;
3 голосов
/ 02 декабря 2009

Согласно документации , временные таблицы удаляются по окончании сеанса.

2 голосов
/ 02 декабря 2009

Да, временная таблица все еще будет существовать. Временные таблицы по определению имеют время жизни сеанса, в котором они были созданы, если они явно не удалены.

Временная таблица может быть видна только сеансу, который ее создал, и нет препятствий для выполнения одной и той же процедуры параллельно несколькими пользователями. Ответ Адама на проверку существования временной таблицы вернет ненулевой результат, если какой-либо пользователь запускает процедуру. Вам необходимо проверить, что сеанс, которому принадлежит временная таблица, также является текущим сеансом. Учитывая, что этот вопрос относится к области хранимой процедуры, может быть проще добавить явный DROP, заключенный в некоторую обработку исключений.

1 голос
/ 02 декабря 2009
SELECT count(*) 
INTO w_count 
FROM sysmaster:systabnames s,sysmaster:systabinfo i
WHERE i.ti_partnum = s.partnum
AND sysmaster:BITVAL(i.ti_flags,'0x0020') = 1
AND s.tabname = 'tempTable' ;

Если w_count равен 1, удалите таблицу перед SELECT ... INTO.То же самое с DROP TABLE.

...