【问题标题】:Oracle Sql : Procedure which can create temporary tables inside itOracle Sql:可以在其中创建临时表的过程
【发布时间】:2013-09-19 18:26:16
【问题描述】:

我是 Oracle Sql 的新手,遇到一个问题:

我想在过程中创建一个临时表。

喜欢:

CREATE PROCEDURE P
  AS
  BEGIN
    CREATE TEMPORARY TABLE A(ID int);
  END P;

但这给了我一个错误

如何在过程中创建临时表。

我在 stackoverflow 上看到了其他答案,但没有正确回答我的问题 你能帮帮我吗?

【问题讨论】:

  • 我认为您想要的是将CREATE GLOBAL TEMPORARY TABLE A(ID INT) ON COMMIT DELETE ROWS 放在程序之外。它将是特定于会话的,并在每次提交时清除。
  • @ManishSharma - 那么你只是产生了每天创建和删除表的成本吗?我不明白为什么您不会像创建系统中的任何其他表一样只创建一次表。您不会有任何引用该表的 PL/SQL 代码?
  • @ManishSharma - 在 Oracle 中,临时表的定义是永久性的。只有表中的数据是临时的。无论该表是临时的还是永久的,每天都创建和删除同一个表是没有意义的。
  • 当然,如果您的过程中途失败,那么无论如何您只是在系统上留下了一个表,并且下次运行该过程时它将失败,因为该表已经存在。您最好还添加代码以检测表是否已存在,如果存在则不要尝试再次创建它。这样,如果您获得永久创建表的权限,您也不必再次重新部署代码。

标签: sql oracle stored-procedures


【解决方案1】:

为什么首先要在存储过程中创建临时表?

在其他数据库(例如 SQL Server 和 MySQL)中创建临时表是比较常见的。在 Oracle 中做同样的事情是非常非常罕见的。几乎在所有你想在 Oracle 中创建临时表的情况下,都有更好的架构方法。 DBA 堆栈上有一个线程讨论 alternatives to temporary tables 以及为什么它们在 Oracle 中不常用。

以编程方式,您可以使用动态 SQL 创建对象

CREATE OR REPLACE PROCEDURE dont_do_this
AS
BEGIN
  EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE a( id INTEGER )';
END;

但是,如果您动态创建一个临时表,则对该表的每次引用也需要通过动态 SQL 进行 - 您将无法针对该表编写简单的 SELECT 语句。 Oracle 中临时表的定义是全局的,因此它对每个会话都是可见的。如果您有两个不同的会话都试图创建同一个表,则第二个会话将出错。如果您希望该表在不同的会话中具有不同的定义,那么您会遇到更多问题。

【讨论】:

  • 但我可以通过正常的选择查询访问该表
  • @ManishSharma - 如果表存在,您可以直接在 PL/SQL 中引用它。但是如果该表可能不存在(如果其他过程正在创建它,则它必须存在),那么您需要使用动态 SQL 来引用该表,否则您的 PL/SQL 块将无法编译。跨度>
【解决方案2】:

您可以将动态 SQL 与 EXECUTE IMMEDIATE 一起使用:

CREATE OR REPLACE
PROCEDURE p
AS
BEGIN
   EXECUTE IMMEDIATE 'CREATE TEMPORARY TABLE A(id NUMBER)...etc';
END p;

编辑:显然你必须确保你的语法在 EXECUTE IMMEDIATE 语句中是正确的。

希望对你有帮助。

【讨论】:

  • -1 帮助别人朝自己的脚开枪是没有帮助的 :)
  • 如果那是他们真正想做的事。人们出于各种原因在这里提问,我回答了所提出的问题。否决票反映了您对他们提出问题的原因的解释,而不是对所提出的实际问题的答案。
  • 不,否决票与答案的帮助程度有关,仅此而已。这涉及到一个判断电话 - 有时即使所采取的方法不是最好的方法,也可以按字面意思回答;但是在其他情况下(例如这种情况),您需要帮助 OP 了解他们完全走错了路。即使是说“你可以这样做,但你很可能不应该这样做,因为......”
  • 我们必须同意不同意,您仍然在假设用户不知道他们为什么要按照他们的问题要求去做。是你的假设导致了反对票。答案很有帮助,因为它回答了所提出的问题。这个网站毕竟是一个问答。如果 OP 要求提供有关要解决的问题的任何进一步信息,那么将提供更多信息,但他们没有。我必须假设 OP 并不愚蠢,所以我只回答提出的问题。
  • 这可能对你有帮助 Ollie:meta.stackexchange.com/questions/191205/…
【解决方案3】:

您必须将您的程序声明为:

create or replace PROCEDURE MYPROCEDURE AUTHID CURRENT_USER IS

script varchar(4000);

BEGIN

script:= 'CREATE GLOBAL TEMPORARY TABLE BNMCODIAGNOSTICASSOCIE_TEMP
ON COMMIT PRESERVE ROWS
as select ........';

EXECUTE IMMEDIATE script;

commit;

END;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2015-09-02
    • 1970-01-01
    • 2012-05-30
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多