Open SQL 基础

Open SQL 基础 (★★)

#abap-basics #open-sql

Open SQL vs. Native SQL

属性 Open SQL Native SQL
集成方式 完全集成在 ABAP 中 嵌入在 EXEC SQL...ENDEXEC 之间
可移植性 与数据库无关 与数据库相关
转换 数据库接口自动转换 直接传递给数据库
缓冲 使用 SAP 表缓冲 绕过 SAP 表缓冲
语法 标准 SQL 子集 特定数据库厂商的 SQL 方言
📌始终优先使用 Open SQL
Open SQL 保证无论安装了什么数据库系统,都能统一访问。数据库接口会动态将 Open SQL 转换为特定数据库的 SQL。

SELECT 语句结构

1
2
3
4
SELECT  <result_columns>        <-- SELECT 子句:单行/多行,哪些列
FROM <database_table> <-- FROM 子句:源表或视图
INTO <target_area> <-- INTO 子句:数据放置位置
WHERE <conditions>. <-- WHERE 子句:筛选行

三种 SELECT 变体

变体 语法 使用场景 需要循环
单条记录 SELECT SINGLE ... 读取恰好一行
顺序处理 SELECT ... ENDSELECT 逐行处理
数组读取 SELECT ... INTO TABLE ... 一次性将所有行复制到内表
📌互斥语法
SINGLEENDSELECTINTO TABLE互斥的。不能在同一个 SELECT 中组合使用。
例外:PACKAGE SIZE(后续介绍)允许将 INTO TABLEENDSELECT 组合使用。

单条记录访问:SELECT SINGLE

1
2
3
4
5
6
SELECT SINGLE *
FROM sflight
INTO ls_flight
WHERE carrid = 'AA'
AND connid = '0017'
AND fldate = '20260510'.
方面 说明
用途 从数据库中读取恰好一条记录
最佳实践 WHERE 中填写所有关键字段以确保唯一访问
* vs. 列列表 * 读取所有列;指定具体列名更高效
sy-subrc 0 = 找到记录;4 = 未找到记录
CORRESPONDING FIELDS OF 按名称逐组件填充目标区域
不使用 CORRESPONDING 按左对齐填充目标,忽略结构
💡SELECT SINGLE 始终要指定 WHERE 子句
没有 WHERE 时,数据库返回任意的单行 – 几乎永远不是你想要的。

顺序处理:SELECT … ENDSELECT

1
2
3
4
5
6
7
SELECT carrid connid fldate price
FROM sflight
INTO (lv_carrid, lv_connid, lv_fldate, lv_price)
WHERE carrid = 'AA'.
" 逐行处理每条记录
WRITE: / lv_carrid, lv_connid, lv_fldate, lv_price.
ENDSELECT.
方面 说明
用途 在循环中逐行处理
数据库交付 数据以包的形式从数据库接口到达
逐行复制 ABAP 运行时按顺序将每条记录复制到目标区域
ENDSELECT 后的 sy-subrc 0 = 至少读取一条记录;4 = 无记录
ENDSELECT 后的 sy-dbcnt 读取的总行数
WHERE 条件 只允许使用数据库表字段名;用 AND/OR 组合
⚠️性能考虑
SELECT ... ENDSELECT 在数据库上打开游标。对于大型结果集,数组读取(INTO TABLE)通常更高效。

数组读取:SELECT … INTO TABLE

1
2
3
4
5
SELECT *
FROM sflight
INTO TABLE lt_flights
WHERE carrid = 'AA'
AND connid IN so_conn.
方面 说明
用途 将整个结果集直接复制到内表
机制 ABAP 运行时直接复制数据 – 无需循环
ENDSELECT 不得编写(数组读取不是循环)
sy-subrc 0 = 至少读取一条记录;4 = 无记录
sy-dbcnt 读取的行数
💡大多数场景优先使用数组读取
INTO TABLE 通常是读取数据最有效的方式,因为它最小化了数据库接口和 ABAP 运行时之间的往返次数。

SELECT 变体比较

1
2
3
4
5
6
7
8
9
                    SELECT SINGLE          SELECT...ENDSELECT        SELECT INTO TABLE
============== ================ =================
目标区域: 结构体 结构体/内表 内表
读取记录: 单行 多行 多行
处理方式: 立即处理 循环体中处理 读取后处理
ENDSELECT: 不需要 需要 不需要
sy-subrc 检查: 立即检查 ENDSELECT 之后 立即检查
sy-dbcnt: 不适用 总行数 总行数
典型用途: 单条查找 逐行处理 批量数据检索

WHERE 子句基础

1
2
3
4
5
6
WHERE carrid = 'AA'                     " 等于
AND connid >= 100 " 比较运算符
AND fldate BETWEEN '20260101' " BETWEEN 范围
AND '20261231'
AND planetype LIKE '74%' " 模式匹配
AND currency IN ('USD', 'EUR'). " IN 列表
运算符 含义
= 等于
<>, != 不等于
>, <, >=, <= 比较
BETWEEN ... AND ... 范围(包含边界)
LIKE 模式匹配(% = 任意字符,_ = 单个字符)
IN (...) 值列表
IS NULL / IS NOT NULL 空值检查

选择屏幕参数

语句 用途 示例
PARAMETERS 单个输入字段 PARAMETERS pa_car TYPE sflight-carrid.
SELECT-OPTIONS 范围/复杂选择 SELECT-OPTIONS so_con FOR gs_flight-connid.

SELECT-OPTIONS 内表结构

使用 SELECT-OPTIONS 声明时,会创建一个包含四个字段的内表:

字段 类型 含义
SIGN c(1) I = 包含,E = 排除
OPTION c(2) 运算符:EQ, NE, BT, CP, GT, GE, LT, LE, NB, NP
LOW (字段类型) 下限值 / 单值
HIGH (字段类型) 上限值(用于 BT/NB

在 WHERE 子句中的使用

1
2
3
4
5
6
PARAMETERS: pa_car TYPE sflight-carrid.
SELECT-OPTIONS: so_con FOR gs_flight-connid.

SELECT * FROM sflight INTO TABLE gt_flight
WHERE carrid = pa_car " 单值参数
AND connid IN so_con. " SELECT-OPTIONS(IN 运算符)
📌WHERE 中使用 IN 处理 SELECT-OPTIONS
SELECT-OPTIONSWHERE 子句中必须使用 IN 运算符。运行时系统会自动将选择表展开为相应的 SQL 条件。

sy-subrc 检查模式

1
2
3
4
5
6
7
SELECT * FROM sflight INTO TABLE gt_flight
WHERE carrid = pa_car
AND connid IN so_con.

IF sy-subrc <> 0.
MESSAGE e038. " 错误:未找到数据
ENDIF.
sy-subrc SELECT SINGLE SELECT … ENDSELECT SELECT INTO TABLE
0 找到记录 至少一条记录 至少一条记录
4 未找到记录 未找到记录 未找到记录
8 (不适用) (不适用) (不适用)

考试/测试模式

关键词 / 问题 答案
“SELECT SINGLE 的 WHERE 需要什么?” 所有关键字段以确保唯一访问
“ENDSELECT 可以与 INTO TABLE 一起使用吗?” 不可以 – 它们互斥
“哪种变体直接将数据复制到内表?” 数组读取(INTO TABLE
“SELECT 后 sy-subrc = 4 表示什么?” 未找到匹配 WHERE 条件的记录
“什么运算符将 SELECT-OPTIONS 连接到 WHERE?” IN(如 WHERE connid IN so_con
“可以不带 WHERE 使用 SELECT 吗?” 可以,但会读取整个表 – 大表很危险
“CORRESPONDING FIELDS OF 的作用是什么?” 按组件名称匹配填充目标,而非左对齐
“SELECT 后 sy-dbcnt 是什么?” 读取的行数(ENDSELECT 或 INTO TABLE 后可用)
“PARAMETERS 和 SELECT-OPTIONS 的区别?” PARAMETERS = 单值;SELECT-OPTIONS = 范围表(SIGN, OPTION, LOW, HIGH)

相关笔记