我可以在调用同一过程后将 PL/SQL 过程放在匿名块中吗?

Posted

技术标签:

【中文标题】我可以在调用同一过程后将 PL/SQL 过程放在匿名块中吗?【英文标题】:Can I drop PL/SQL procedure in Anonymous block just after called the same procedure? 【发布时间】:2020-10-12 00:25:51 【问题描述】:

我创建了一个 PL/SQL 存储过程,用于将行插入到相关表中,然后在另一个 PL/SQL 匿名块中,我可以单独调用和删除它。但是,当把这两个语句放在一起时,Sql developer 只是永远持续在那里运行。下面是三个代码sn-ps:

-- 下面的代码运行良好

BEGIN
  MyProcedure1 (1,70,'Tommy'); 
END;  

-- 下面的代码运行良好

BEGIN
  EXECUTE IMMEDIATE 'drop procedure MyProcedure1';
END;

-- 下面的代码永远卡在那里

BEGIN
  MyProcedure1 (1,70,'Tommy'); 
  EXECUTE IMMEDIATE 'drop procedure MyProcedure1';
END;

【问题讨论】:

我想不出你想要这样做的任何场景,如果你能提供一些背景信息来说明你为什么要这样做,那将会很有帮助。这可能使人们能够就如何以不同方式/更好地实现您的目标向您提出建议。 我有一批记录要插入到具有特定过程的表中,这是客户的要求。程序没有问题。所以我只需要写一个新的脚本来用这个程序插入相关数据,并且在插入所有这些行之后,我还想在同一个脚本中删除这个特定的程序,然后遇到上述问题。 其实我做过一个相关的测试:我创建了另外一个程序(很简单,甚至没有任何参数),然后在另一个脚本中(必须有Begin和End,相关语句就定位它们之间),我调用这个新程序然后使用“立即执行”dropt 程序----然后结果是一样的,代码卡在那里! 所以问题很简单:在PL/SQL的匿名块中,我们可以调用一个过程然后使用EXECUTE IMMEDIATE删除它吗? --- 此代码与具体业务逻辑无关 基本上每个人都可以在自己的环境中测试两分钟 【参考方案1】:

David,我仍然看不出为什么在插入数据后您需要立即删除该过程....如果您想明天插入更多数据怎么办?如果它只是一次性的东西,为什么你不能事后手动删除它?

但是如果你真的必须这样做......

BEGIN
  MyProcedure1 (1,70,'Tommy'); 
END;
/
drop procedure MyProcedure1;

然后单击 SqlDeveloper 中的 run as script 按钮...运行没有问题,查看会话管理器正在发生的事情是匿名块将过程放入缓存/固定它(意味着没有其他东西可以编译/删除它)直到该块完成。这就是为什么将 drop 移到 Begin / End 之外允许代码工作的原因。

【讨论】:

嗨,肖恩,感谢您的解决方案和解释!该程序只是为了插入这个批次数据,客户不希望运行两个脚本来完成一个任务。【参考方案2】:

如果你查询v$session,这就是你所看到的(当然,当匿名 PL/SQL 块仍在“运行”时——实际上,它正在等待):

SQL> select
  2    a.blocking_session,
  3    b.username blocking_username,
  4    b.osuser blocking_osuser,
  5    a.sid,
  6    a.serial#,
  7    a.seconds_in_wait,
  8    a.username,
  9    a.wait_class,
 10    a.state
 11  from v$session a join v$session b on a.blocking_session = b.sid;

BLOCKING_SESSION BLOCKING_USERNAME BLOCKING_OSUSER  SID  SERIAL# SECONDS_IN_WAIT USERNAME WAIT_CLASS  STATE
---------------- ----------------- --------------- ---- -------- --------------- -------- ----------- -------
             707 SCOTT             littlefoot       707     1245             329 SCOTT    Concurrency WAITING

SQL>

注意最后两列:

state = 等待 wait_class = 并发

是谁造成的?我自己。所以是的 - 我们遇到了敌人,他们就是我们

看起来你不能按照你想要的方式做,而是分开做:

先调用过程 完成后,放下它

不过,多么奇怪的要求……你为什么要放弃一个程序? 明天你会再次创建它吗?如果是这样,为什么要放弃它?说“客户需要它”——客户到底知道什么?让他们三思而后行;如果这还不够,请再想一想。

【讨论】:

您好 Littlefoot,感谢您的解释!该程序只是为了插入这批数据,客户不想运行两个脚本来完成一个任务。

以上是关于我可以在调用同一过程后将 PL/SQL 过程放在匿名块中吗?的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL - 调用包过程的新实例

是否可以在 PL/SQL 开发人员测试窗口的“声明”块中声明子过程?

将数组发送到 PL/SQL 过程

ORACLE PL/SQL:以最大执行时间调用外部 Oracle PL/SQL 过程

如何在 Pl/SQL 中正确创建一个过程,在该过程中我创建一个表并使用一个游标

如何在javascript中调用pl/sql过程和函数?