【问题标题】:Stored function not firing in "insert into" subquery存储函数未在“插入”子查询中触发
【发布时间】:2012-07-17 14:18:43
【问题描述】:

我在 ORACLE 11g 上使用 SQL 插入到 table1 并同时触发插入到 table3 的存储函数。存储函数没有触发,我怀疑这是因为 ORACLE 优化器意识到插入 table1 不需要存储函数,所以它忽略了它们? 有没有办法请求oracle不优化查询或者有更好的解决方案。 示例代码:

INSERT INTO table1 (col1)
SELECT A.col1
FROM (SELECT col1, storedFunction(col2),storedFunction(col3),storedFunction(col4)
FROM table2) A  

【问题讨论】:

  • 您之前是否尝试将所有数据插入到临时表中?
  • 究竟想做什么?对一组记录多次调用一个过程或同时插入多个表?
  • danhip - 这是一种可能性,但我插入了 >1 亿行,所以我想(如果可能的话)在 1 个查询中完成
  • Adam - 添加到我的示例代码中。多次调用storedProcedure,每次插入table3
  • 首先,我假设它实际上是一个存储函数,而不是存储过程,因为存储过程不能在 SQL 语句中调用。但是,插入另一个表的存储函数也不能从 SQL 语句中调用。这意味着您的存储函数是使用自治事务声明的,该事务引入了一堆皱纹,没有一个是好的。为插入到table3 中的每一行提交将非常昂贵。您存储的函数将无法查看会话中未提交的更改。这是怎么回事?

标签: sql oracle stored-procedures oracle11g


【解决方案1】:

您可以让您的存储过程返回 NULL 并使用以下内容:

INSERT INTO table1 (col1)
SELECT NVL( col1, storedProcedure(col2) )
FROM table2

NVL 总是计算两个参数,即使第一个参数不为空。

我不确定我是否会对这种 hack 感到满意...

【讨论】:

  • Peter - 不幸的是,这不是我的存储过程,它返回一个数字,但感谢您的建议。
  • 你可以用你自己的返回 NULL 的函数来包装这个函数,但正如亚当所说,试着重新考虑这个策略......
【解决方案2】:

鉴于您的 storedFunction 是一个自治事务,并且您正在处理超过 1 亿行,您可能会遇到严重的性能问题。如果可能的话,我会重新考虑整个策略。报废它。重新开始。

选项 1

如果这不可能,最好的办法是执行bulk collect fetches(有限制)以检索col1col2,为每一行的col2 显式调用storedFunction,然后@987654327 @变成table1。这有望最大限度地减少从table2 读取和写入table1 的I/O。不过,您确实会在致电 storedFunction 时向吹笛者付费。

选项 2 将您的函数包装在另一个具有您想要的行为的函数中。你没有提到类型,但我假设 VARCHAR2。当然,您可以根据需要进行调整。 请原谅语法错误,因为我手头没有 Oracle 数据库。

CREATE FUNCTION MYFUNC(col1 IN VARCHAR2, col2 IN VARCHAR2) RETURN VARCHAR2
AS
   v_dummy VARCHAR2(100);
BEGIN
  v_dummy := storedFunction(col2);   --Call stored function
  return col1;                       --return col 1 unchanged
END;

然后你可以按如下方式进行插入:

INSERT INTO table1 (col1)
SELECT MYFUNC(A.col1, A.col2)
FROM   table2 A;  

【讨论】:

  • Adam = 我意识到我可以使用 PL/SQL 来做到这一点。当它在 SQL 中不起作用时,我感到很惊讶,我想知道是否有人有 1 查询 SQL 解决方案。不过,我坚持使用 storedFunction。
  • 我只是被一个使用自主事务的函数吓坏了。 颤抖
【解决方案3】:

SQL 的解决方案是将子查询做成临时表,并在子查询中使用/*+ MATERIALIZE */ 提示来强制Oracle 对存储的Functions 进行求值。 例如

INSERT INTO table1 (col1)
WITH temp_table AS (/*+ MATERIALIZE */  SELECT col1, storedFunction(col2),storedFunction(col3),storedFunction(col4)
FROM table2) 
SELECT col1
FROM temp_table

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多