隐式游标仅适用于确定单行返回的场景,如查主键或唯一键;多行必须用显式游标,否则会出错;SELECT INTO 无行数校验,0行抛ORA-01403,>1行抛ORA-01422;SQL%NOTFOUND不可作循环条件;显式游标优先用FOR循环自动管理;BULK COLLECT必须带LIMIT并配合DELETE防内存溢出。

隐式游标只适用于**确定单行返回**的场景,比如查主键、唯一键或配置表固定键值;多行处理必须用显式游标,否则不是慢,而是会出错或崩溃。
SELECT INTO 必须保证至多返回一行
隐式游标最常出现在 SELECT ... INTO 语句中,但它不是“自动安全”的——Oracle 不做行数校验,只在运行时抛异常。
- 返回 0 行 → 触发
ORA-01403: no data found,需用EXCEPTION WHEN NO_DATA_FOUND THEN捕获 - 返回 >1 行 → 触发
ORA-01422: exact fetch returns more than requested number of rows,无法靠%NOTFOUND预防 -
SQL%NOTFOUND只反映上一次 DML 或SELECT INTO的结果,不能当循环条件用(它不是游标状态) - 典型安全用法:
SELECT value INTO v_timeout FROM config WHERE key = 'SESSION_TIMEOUT',前提是key有唯一约束
显式游标要配对 OPEN/CLOSE,且优先用 FOR 循环
手动管理显式游标(OPEN/FETCH/CLOSE)容易漏关,导致 ORA-01000: maximum open cursors exceeded;而 FOR rec IN cursor_name LOOP 自动处理生命周期,更安全。
- 显式游标声明后必须
OPEN才能FETCH,未CLOSE的游标会持续占用会话资源 -
FOR循环隐式完成OPEN、逐行FETCH、CLOSE,且默认启用 array fetch(通常一次取 15 行),比手动循环快得多 - 若需控制批量大小(如防内存溢出),改用
FETCH c BULK COLLECT INTO t LIMIT 100,但必须配合t.DELETE清空集合,否则下次BULK COLLECT会追加而非覆盖
BULK COLLECT 不带 LIMIT 是内存炸弹
很多人以为用了 BULK COLLECT 就等于“高性能”,其实没加 LIMIT 的写法等价于全量加载到 PGA,极易触发 ORA-04030(内存不足)。
- 单行平均 2KB,取 1000 行 ≈ 2MB;并发 10 个会话就吃掉 20MB PGA,远超多数 OLTP 实例默认分配
- 实测安全临界点通常在 100–500 行之间,取决于字段宽度(尤其含
VARCHAR2(4000)或CLOB时)和并发压力 - 必须写成
FETCH c BULK COLLECT INTO t LIMIT 100,且循环内加t.DELETE,否则集合持续膨胀
游标类型选择不是语法习惯问题,而是数据契约问题:你得先确认“这条 SQL 是否保证至多返回一行”,再决定用不用 SELECT INTO;而不是反过来,拿隐式游标去硬扛多行逻辑。


















