LOB 流与定位器

LOB 流与定位器 (★★)

#open-sql #lobs #database

LOB 类型

LOB 类型 ABAP 类型 数据库类型 内容
二进制 LOB xstring BLOB 二进制数据(图像、PDF 等)
字符 LOB string CLOB 文本数据(文档、XML 等)

访问方法比较

方法 传输方式 内存 使用场景
普通(直接) 完整 LOB 到 ABAP 高(完整内容在内存中) 小 LOB,需要全部内容
顺序读/写 低(逐块处理) 大 LOB,顺序处理
定位器 元数据 + 子序列 很低 检查长度、提取部分、在数据库端复制

普通访问(完整传输)

1
2
3
4
5
" 完整传输 - 将整个 LOB 加载到内存
SELECT document_content
INTO lv_string " 类型 STRING = 完整 CLOB 传输
FROM documents
WHERE doc_id = '001'.
⚠️普通访问将整个 LOB 传输到应用服务器。对于大文档(兆字节级),这会导致高内存消耗。

流(NW 7.0 EhP2+)

无需完整传输的顺序读/写。

读取器类

用途
CL_ABAP_DB_C_READER 读取 CLOB(字符)
CL_ABAP_DB_X_READER 读取 BLOB(二进制)
CL_ABAP_DB_C_WRITER 写入 CLOB
CL_ABAP_DB_X_WRITER 写入 BLOB(二进制)

流方法

方法 用途
DATA_AVAILABLE() 检查是否有更多数据可读
READ(length) 读取指定长度的下一块
SKIP(length) 跳过字节/字符
CLOSE() 关闭流并释放资源
IS_CLOSED() 检查流是否已关闭

流读取示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DATA: lo_reader TYPE REF TO cl_abap_db_c_reader.

SELECT document_content
INTO lo_reader " 流对象而非字符串
FROM documents
WHERE doc_id = '001'.

WHILE lo_reader->data_available( ) = abap_true.
lv_chunk = lo_reader->read( 1000 ). " 每次读取 1000 字符
" 处理 lv_chunk
ENDWHILE.

lo_reader->close( ).
ENDSELECT.

流写入示例

1
2
3
4
5
6
7
DATA: lo_writer TYPE REF TO cl_abap_db_x_writer.

INSERT INTO documents VALUES ( '002', lo_writer ).

lo_writer->write( lv_data_chunk1 ).
lo_writer->write( lv_data_chunk2 ).
lo_writer->close( ).
📌每个会话最多同时打开 16 个流。尽快关闭流以释放资源。

定位器

无需完整传输即可访问 LOB 元数据和子序列。可以在数据库端复制 LOB 而无需传输到应用服务器。

定位器类

用途
CL_ABAP_DB_C_LOCATOR 字符 LOB 定位器
CL_ABAP_DB_X_LOCATOR 二进制 LOB 定位器

定位器方法

方法 用途
GET_LENGTH() 获取 LOB 长度而不传输
FIND(substring) 在 LOB 中搜索
GET_SUBSTRING(offset, length) 提取 LOB 的一部分
CLOSE() 释放定位器

定位器示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DATA: lo_locator TYPE REF TO cl_abap_db_c_locator.

SELECT document_content
INTO lo_locator
FROM documents
WHERE doc_id = '001'.

lv_length = lo_locator->get_length( ). " 无数据传输
lv_pos = lo_locator->find( 'IMPORTANT' ). " 在数据库端搜索
lv_excerpt = lo_locator->get_substring( " 仅传输这部分
offset = lv_pos - 50
length = 100 ).

lo_locator->close( ).
ENDSELECT.
💡定位器可以在数据库端直接复制 LOB(数据库端复制),完全避免传输到应用服务器。
📌每个 LUW 最多 1000 个打开的 LOB 句柄(流 + 定位器合计)。

流和定位器的缺点

缺点 详情
更高的数据库资源消耗 数据库保持游标/锁打开
数据库依赖性 并非所有数据库原生支持
复杂性 比简单 SELECT 代码更多
限制 16 个流,每个 LUW 1000 个 LOB 句柄

流 vs 定位器

特性 定位器
访问模式 仅顺序 随机访问
读取分块 是(READ(length) 是(GET_SUBSTRING
写入 是(写入器类)
搜索 是(FIND
获取长度 是(GET_LENGTH
数据库端复制
最大打开数 16 与流合计 1000

考试/测试模式

关键词 / 短语 答案
“最大打开流数” 每个会话 16 个
“每个 LUW 最大 LOB 句柄” 1000 个(流 + 定位器合计)
“BLOB 读取的流类” CL_ABAP_DB_X_READER
“CLOB 写入的流类” CL_ABAP_DB_C_WRITER
“定位器相比流的优势” 随机访问、搜索、获取长度、数据库端复制
“普通访问的缺点” 完整传输到内存(高消耗)
“DATA_AVAILABLE 方法” 检查流中是否有更多数据可用
“定位器上的 GET_LENGTH” 返回长度而不传输 LOB 内容

相关笔记