临时表的生命周期
我有以下过程:
CREATE PROCEDURE foo ()
SELECT * FROM fooBar INTO TEMP tempTable;
-- do something with tempTable here
DROP TABLE tempTable;
END PROCEDURE;
如果在调用 DROP TABLE 之前出现异常会发生什么? foo 退出后 tempTable 还会存在吗?
如果是这样, foo 下次调用时可能会失败,因为 tempTable 已经存在。那应该怎么处理呢。
编辑:我正在使用 informix 11.5
I have the following procedure:
CREATE PROCEDURE foo ()
SELECT * FROM fooBar INTO TEMP tempTable;
-- do something with tempTable here
DROP TABLE tempTable;
END PROCEDURE;
What happens if there is an exception before the DROP TABLE is called? Will tempTable still be around after foo exits?
If so, foo could fail the next time it is called, because tempTable would already exist. How should that be handled.
EDIT: I am using informix 11.5
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
根据根据文档,会话结束时临时表将被删除。
According to the documentation, temporary tables are dropped when the session ends.
正如其他人所说,临时表会一直持续到您显式删除它们或会话结束为止。
如果存储过程因表已存在而失败,则 SPL 会生成异常。
您可以通过添加 ON EXCEPTION 子句来处理异常 - 但您正在进入 SPL(存储过程语言)中更为巴洛克的部分之一。
这是存储过程的一个稍微修改的版本 - 一个生成被零除异常的版本(SQL -1202):
这表明第一次执行代码时执行了 SELECT,创建了表,然后违反了除以零。但第二次,SELECT 失败,因为临时表已经存在,因此出现不同的错误消息。
BEGIN/END 块将异常处理限制为捕获的语句。如果没有 BEGIN/END,异常处理会覆盖整个过程,也会对被零除错误做出反应(因此让 DROP TABLE 工作并且过程似乎成功运行)。
请注意,此时 temptable 仍然存在:
这表明该过程不再因临时表存在而失败。
您可以通过以下方式将 ON EXCEPTION 块限制为选定的错误代码(对于此错误代码,-958 似乎是合理的):
请参阅 IBM Informix Guide to SQL: Syntax 手册,第 3 章“SPL 语句”。
请注意,Informix 11.70 在 CREATE 和 DROP 语句中添加了“IF EXISTS”和“IF NOT EXISTS”子句。因此,您可以使用修改后的 DROP TABLE 语句:
因此,对于 Informix 11.70 或更高版本,编写该过程的最简单方法是:
您也可以使用此语句,但随后您将获得该过程的先前定义,无论它是什么,并且它可能不是你所期望的。
As others stated, temporary tables last until you drop them explicitly or the session ends.
If the stored procedure fails because the table already exists, SPL generates an exception.
You can deal with exceptions by adding an ON EXCEPTION clause -— but you are entering one of the more baroque parts of SPL, Stored Procedure Language.
Here is a mildly modified version of your stored procedure - one that generates a divide by zero exception (SQL -1202):
This shows that the first time through the code executed the SELECT, creating the table, and then ran foul of the divide by zero. The second time, though, the SELECT failed because the temp table already existed, hence the different error message.
The BEGIN/END block limits the exception handling to the trapped statement. Without the BEGIN/END, the exception handling covers the entire procedure, reacting to the divide by zero error too (and therefore letting the DROP TABLE work and the procedure seems to run successfully).
Note that temptable still exists at this point:
This shows that the procedure no longer fails because the temp table is present.
You can limit the ON EXCEPTION block to selected error codes (-958 seems plausible for this one) by:
See the IBM Informix Guide to SQL: Syntax manual, chapter 3 'SPL Statements'.
Note that Informix 11.70 added the 'IF EXISTS' and 'IF NOT EXISTS' clauses to CREATE and DROP statements. Thus, you might use the modified DROP TABLE statement:
Thus, with Informix 11.70 or later, the easiest way to write the procedure is:
You could also use this, but then you get the previous definition of the procedure, whatever it was, and it might not be what you expected.
我最终使用了 Jonathan 和 RET 解决方案的变体:
I finally used a variation of Jonathan's and RET's solution:
是的,临时表仍然存在。根据定义,临时表具有创建它们的会话的生命周期,除非显式删除。
临时表只能由创建它的会话看到,并且不妨碍多个用户并行运行同一过程。如果任何用户正在运行该过程,Adam 对测试临时表是否存在的答案将返回非零结果。您需要测试拥有临时表的会话是否也是当前会话。鉴于此问题属于存储过程的范围,因此添加显式 DROP(包含在一些异常处理中)可能会更简单。
Yes, the temp table will still exist. Temp tables by definition have a lifetime of the session that created them, unless explicitly dropped.
The temp table can only be seen by the session that created it, and there is no impediment to the same procedure being run in parallel by multiple users. Adam's answer to test for the existence of the temp table will return a non-zero result if any user is running the procedure. You need to test that the session that owns the temp table is the current session as well. Given that this question is within the scope of a stored procedure, it might be simpler to add an explicit DROP, wrapped in some exception handling.
如果w_count为1,则在SELECT ... INTO之前删除表。与删除表相同。
If w_count is 1, delete table before SELECT ... INTO. Same with DROP TABLE.