存储函数未在“插入”子查询中触发

时间:2012-07-18 14:02:33

标签: sql oracle stored-procedures oracle11g

我在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  

3 个答案:

答案 0 :(得分:2)

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

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

NVL总是评估这两个参数,即使第一个参数不为空。

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

答案 1 :(得分:1)

鉴于您的storedFunction作为自治交易工作,并且您正在处理> 1亿行,您可能会遇到严重的性能问题。如果可能的话,我会重新考虑整个战略。报废它。重新开始。

选项1

如果无法做到这一点,最好的办法是执行bulk collect次提取(有限制)以检索col1col2,明确调用storedFunction对于每行col2,然后bulk insert进入table1。这应该有希望最小化来自table2的读取的I / O并写入table1。你打算通过拨打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;  

答案 2 :(得分:1)

SQL解决方案是使子查询成为临时表,并使用子查询中的/*+ MATERIALIZE */提示强制Oracle评估存储的函数。 e.g。

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