You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PL/SQL中依赖变量的游标为何能正常运行?

关于PL/SQL动态游标运行原理的疑问

示例代码

DECLARE
    PIDM            NUMBER(8);
    CLM_TEST_SCORE  NUMBER(5);
    CURSOR C_STUDENT IS
        select PIDM
        from   SOSC.DW_ALL_COLLECTOR
        order by PIDM;

    CURSOR C_CLM_SCORES IS
        select max(to_number(SORTEST_TEST_SCORE))
        from   SATURN.SORTEST
        where  SORTEST_PIDM   = pidm;
BEGIN
    OPEN C_STUDENT;
    LOOP
        CLM_TEST_SCORE := '';

        FETCH c_Student INTO pidm;
        EXIT WHEN c_Student%notfound;

        OPEN C_CLM_SCORES;
        FETCH C_CLM_SCORES INTO CLM_TEST_SCORE;
        CLOSE C_CLM_SCORES;
        
        insert into some_table (CLM_TEST_SCORE)
        values (CLM_TEST_SCORE);

    END LOOP;
END;

疑问

我注意到C_CLM_SCORES游标中引用的pidm是第2行声明的PIDM变量,这意味着游标对应的查询会随着循环每次迭代中pidm的当前值变化。但我之前理解游标是“执行中的查询”,底层查询不应该在每次循环时改变,可这段代码实际能正常运行,想了解它的运行原理是什么?


解答

你遇到的是PL/SQL中静态游标引用PL/SQL变量的典型场景,核心原理如下:

  • C_CLM_SCORES属于静态游标,它的查询文本结构是固定的,但WHERE子句引用了PL/SQL块内的PIDM变量。
  • 游标并非在定义阶段就执行查询,而是每次调用OPEN时才会触发查询的执行准备:此时Oracle会读取PIDM变量的当前有效值,将其作为绑定变量代入查询条件,生成对应的执行计划(符合条件时会复用共享池中的执行计划),随后执行查询获取结果。
  • 你之前的误解混淆了“游标定义”和“游标执行时机”:游标定义只是固定了查询的框架,而每次打开时会动态注入变量的当前值,因此每次循环中查询的过滤条件会随PIDM的变化而变化,代码自然能正常运行。

额外提一句:这种写法虽然可行,但效率较低——每次循环都要打开、关闭游标,会带来不必要的上下文切换开销。更优的写法是使用参数化游标(定义时显式传入参数),或者直接用关联查询一次性完成数据处理,避免嵌套游标操作。比如参数化游标可以这么写:

CURSOR C_CLM_SCORES(p_pidm NUMBER) IS
    select max(to_number(SORTEST_TEST_SCORE))
    from   SATURN.SORTEST
    where  SORTEST_PIDM = p_pidm;
-- 打开时传入参数
OPEN C_CLM_SCORES(pidm);

内容的提问来源于stack exchange,提问作者Jakob Lovern

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:31:22