sql - 光标的替代品
问题描述
我有一个函数,每次调用都会改变它的值。我想在查询中多次使用这个值,但我不想多次执行它,因为我想要第一次调用的值。我努力了:
SELECT RESULT value1,
RESULT value2,
RESULT value3
FROM (SELECT function_invocation() RESULT
FROM dual);
但是每个 VALUE 列都给了我不同的值,这意味着该函数被多次调用。
另一种方法是编写游标,但我想知道是否可以使用纯 SQL。
解决方案
有一些技巧可以防止 Oracle 不必要地重新执行函数。这个主题很困难,因为 99.9% 的时间我们依赖 Oracle 自动重写查询以优化运行。停止这些优化不应该是一项常见的任务。
理论上,没有办法保证声明式 SQL 语句的操作顺序。在实践中,有两种简单的技术可以帮助防止函数重新运行:标量子查询缓存和ROWNUM
.
首先,让我尝试重现该问题。单个值引用返回三个不同的数字。
create or replace function function_invocation return number is
begin
return dbms_random.value;
end;
/
SELECT RESULT value1,
RESULT value2,
RESULT value3
FROM (SELECT function_invocation() RESULT
FROM dual);
VALUE1 VALUE2 VALUE3
------ ------ ------
0.3089 0.7103 0.2885
重写查询以使用标量子查询似乎没有必要,但这种形式使 Oracle 能够使用标量子查询缓存,这是 Oracle 用来避免重新运行代码的一种优化技术。现在三列返回相同的值。
select result value1, result value1, result value1
from
(
select (select function_invocation() from dual) result from dual
);
VALUE1 VALUE2 VALUE3
------ ------ ------
0.2450 0.2450 0.2450
ROWNUM
或者,我们可以通过添加伪列来防止优化转换:
SELECT RESULT value1,
RESULT value2,
RESULT value3
FROM (SELECT function_invocation() RESULT, rownum
FROM dual);
VALUE1 VALUE2 VALUE3
------ ------ ------
0.1678 0.1678 0.1678
这些技术在实践中效果很好,可以使结果看起来正确。但是,该函数可能会在执行之前秘密运行一段时间。额外的运行用于解析和缓存,不会影响结果。但是,如果您有一个只能运行一次的具有副作用的函数,那么您必须跳过一些额外的障碍。
推荐阅读
- haskell - 对 Haskell lambdas 中的参数感到困惑
- botframework - 是否可以通过 Azure Pipelines 刷新 Bot Framework Orchestrator 模型?
- flutter - 如何根据 GA 上的屏幕标题过滤 screen_view 分析?
- python-3.x - Python ZMQ Publisher 连接到 GNUradio SUB 消息源块问题
- python - 从 .pcd 读取点云到 ROS PointCloud2
- django - 如何在 Django ListView 中列出模型字段的子字段?
- python - Kivy 问题 - 无法获取窗口,中止
- django - Google Analytics Measurement Protocol 无法跟踪购物车添加和产品视图
- xcode - 静态方法“buildBlock”需要“ToolbarItem”
'符合'视图' - python - 用于在 Windows 上打开的 Linux 文本文件编码