【发布时间】:2016-03-03 12:52:01
【问题描述】:
在 Oracle 12c 中,如果我在使用 WITH..AS 部分中的 MATERIALIZE 提示的查询中调用函数,则函数调用的行为类似于自主事务:
DROP TABLE my_table;
CREATE TABLE my_table (
my_column NUMBER
);
-- Returns number of records in table
CREATE OR REPLACE FUNCTION my_function
RETURN INTEGER
IS
i INTEGER;
BEGIN
SELECT COUNT(1) INTO i FROM my_table;
RETURN i;
END;
/
-- Inserts one record to table
INSERT INTO my_table (my_column) VALUES (9);
-- Returns number of records in table. This works correctly, returns 1
SELECT COUNT(1) AS "use simple select" FROM my_table;
-- Returns number of records in table. This works correctly, returns 1
WITH x AS (
SELECT /*+ MATERIALIZE */ COUNT(1) AS "use WITH, MATERIALIZE" FROM my_table
)
SELECT * FROM x;
-- Returns number of records in table. This works correctly, returns 1
SELECT my_function AS "use FUNCTION" FROM dual;
-- Returns number of records in table. This works INCORRECTLY, returns 0.
-- Function is called in autonomous transaction?
WITH x AS (
SELECT /*+ MATERIALIZE */ my_function "use WITH,MATERIALIZE,FUNCTION" FROM dual
)
SELECT * FROM x;
ROLLBACK;
有人知道这是什么原因吗?它是 Oracle 错误还是打算像这样工作? (为什么?) 为什么只有当 WITH 与 MATERIALIZED 提示和 FUNCTION 调用结合使用时才会这样?
【问题讨论】:
-
无法在 Oracle 12c 上重现,在我的情况下,最后一次选择返回 1。
-
我猜 Peti 在 12.1.0.1 上,而 Husqvik 在 12.1.0.2 上?
-
它看起来像一个错误。但通常 AFAIK 预期的行为是未定义的。解决方案是永远不要使用递归 SQL。
SELECT count(1)函数在不同的 SCN 上下文中运行,因此它可以看到幻像数据。尝试使用SERIALIZABLE隔离级别。或者尝试也选择实际的数据库 SCN。当然,你的发现是相反的,你看不到应该看到的数据。 -
在这里看起来与此类似:hourim.wordpress.com/2012/07/23/materialize-hint-again 并且正如 Alex 指出的那样,在与此相关的问题上存在一个已注册的错误。所以是的 - 它似乎是与未记录的 Materialize 提示相关的 Oracle 错误......
标签: oracle function common-table-expression