жизненный период таблицы temp
У меня есть следующая процедура:
CREATE PROCEDURE foo ()
SELECT * FROM fooBar INTO TEMP tempTable;
-- do something with tempTable here
DROP TABLE tempTable;
END PROCEDURE;
что произойдет, если есть исключение до вызова таблицы перетаскивания? Будет ли tempTable все еще вокруг после выхода foo?
Если это так, foo может потерпеть неудачу при следующем вызове, потому что tempTable уже будет существовать. Как с этим справиться?
EDIT: я использую informix 11.5
5 ответов
как заявили другие, временные таблицы длятся до тех пор, пока вы не удалите их явно или сеанс не закончится.
если хранимая процедура завершается с ошибкой, поскольку таблица уже существует, 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, создав таблицу, а затем запустил фол деления на ноль. Во второй раз, однако, выбор не удался, потому что временная таблица уже существовала, следовательно, другое сообщение об ошибке.
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 ограничивает обработку исключений заблокированным оператором. Без начала / конца обработка исключений охватывает всю процедуру, реагируя на деление на ноль ошибка тоже (и, следовательно, позволяя DROP TABLE работать, и процедура, кажется, выполняется успешно).
обратите внимание, что temptable все еще существует в этот момент:
+ 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 Guide to SQL: руководство по синтаксису, Глава 3 ' SPL Заявления.'
- Для Informix 12.10 заявления SPL
- Для Informix 11.70 заявления SPL
- Для Informix 11.50 заявления SPL
обратите внимание, что Informix 11.70 добавил предложения "если существует" и "если не существует" для создания и удаления операторов. Таким образом, вы можете использовать modified УДАЛИТЬ о себе:
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;
согласно документации временные таблицы удаляются после окончания сеанса.
Я, наконец, использовал вариант решения Джонатана и РЕТА:
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;
да, временная таблица будет существовать. Временные таблицы по определению имеют время жизни сеанса, который их создал, если явно не удален.
временная таблица может быть видна только сеансом, который ее создал, и нет никаких препятствий для выполнения одной и той же процедуры параллельно несколькими пользователями. Ответ Адама на тест на наличие временной таблицы вернет ненулевой результат, если какой-либо пользователь выполняет процедуру. Вам нужно проверить, что сеанс, которому принадлежит таблица temp также является текущей сессией. Учитывая, что этот вопрос находится в области хранимой процедуры, может быть проще добавить явное падение, обернутое некоторой обработкой исключений.
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, Удалите таблицу перед выбором ... В. То же самое с DROP TABLE.