117 lines
4.0 KiB
Markdown
117 lines
4.0 KiB
Markdown
---
|
||
title: "NW 7.40 Open SQL @ 转义一致性错误"
|
||
created: 2026-08-05
|
||
updated: 2026-08-07
|
||
type: error
|
||
tags: [adt, sap, error, nw740, open-sql, syntax]
|
||
adt_endpoint: syntax-check
|
||
nw_version: 7.40
|
||
confidence: high
|
||
contradictions: []
|
||
---
|
||
|
||
# NW 7.40 Open SQL @ 转义一致性错误
|
||
|
||
## 症状
|
||
|
||
```
|
||
✗ 语法检查未通过! 2 个错误, 0 个警告
|
||
[错误] 行 1: If the new Open SQL syntax is used, it must be used throughout.
|
||
This includes using @ to escape host variables.
|
||
[错误] 行 2: When escaped, all host variables must be escaped using @.
|
||
```
|
||
|
||
## 根因
|
||
|
||
NW 7.40 要求 Open SQL 中的 `@` 转义**全局一致**:
|
||
- 如果在任何一个 SELECT 语句中使用了 `@`(如 `WHERE field = @lv_var`),则**所有** SELECT 语句的 INTO 子句也必须使用 `@`(`INTO TABLE @lt_data`)
|
||
- 反之,如果不用 `@`,全都不用
|
||
- **混用会导致语法检查失败**
|
||
|
||
典型触发场景:将 `@DATA(...)` inline 声明改为传统 `DATA` 声明时,误把 `@` 一起删了。
|
||
|
||
```abap
|
||
" ❌ 错误 — 混用
|
||
SELECT * FROM ztable WHERE field = @lv_var INTO TABLE lt_data.
|
||
|
||
" ✅ 正确 — 全部用@
|
||
SELECT * FROM ztable WHERE field = @lv_var INTO TABLE @lt_data.
|
||
|
||
" ✅ 同样正确 — 全部不用@ (NW 7.40 传统风格)
|
||
SELECT * FROM ztable WHERE field = lv_var INTO TABLE lt_data.
|
||
```
|
||
|
||
## 解决方案
|
||
|
||
**步骤 1**:检查源码中所有 `@` 使用情况
|
||
|
||
```bash
|
||
grep -n "@" program.abap | grep -v "^\*"
|
||
```
|
||
|
||
**步骤 2**:确保一致性
|
||
|
||
- 如果大部分语句已用 `@`:给少数未用的补上 `@`
|
||
```bash
|
||
sed -i 's/INTO TABLE lt_/INTO TABLE @lt_/g' program.abap
|
||
```
|
||
- 如果决定不用 `@`(纯 7.40 传统风格):删掉所有 `@`
|
||
```bash
|
||
sed -i 's/@\(lv_\|ls_\|lt_\|p_\|s_\|abap_\)/\1/g' program.abap
|
||
```
|
||
|
||
**步骤 3**:重新语法检查
|
||
|
||
```bash
|
||
python main.py syntax-check --name ZXXX --type report
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
- `CONCATENATE ... INTO`(字符串操作)不需要 `@`
|
||
- `LOOP AT ... INTO`(内表循环)不需要 `@`
|
||
- `CATCH ... INTO`(异常处理)不需要 `@`
|
||
- **只有 SELECT 语句的 INTO/WITH 子句受此规则约束**
|
||
|
||
## 代码示例
|
||
|
||
```abap
|
||
" 修复前(混用→语法错误)
|
||
DATA lt_data TYPE STANDARD TABLE OF ztable.
|
||
SELECT * FROM ztable WHERE field = @lv_var INTO TABLE lt_data. " WHERE有@, INTO没有
|
||
|
||
" 修复后(一致)
|
||
SELECT * FROM ztable WHERE field = @lv_var INTO TABLE @lt_data. " 全部用@
|
||
```
|
||
|
||
## 相关错误
|
||
|
||
- [[adt-set-source-500]] — 传输请求无对象导致写入失败
|
||
|
||
## 2026-08-07 实测补充:全 @ 场景强制 new OpenSQL 语法(新坑)
|
||
|
||
**症状**:已修复 @ 一致性(INTO 目标补 @)后,又报新错误:
|
||
```
|
||
If host variables are escaped using @, new OpenSQL must used
|
||
```
|
||
|
||
**根因**:@ 转义属于"新 OpenSQL"语法体系。一旦语句用了 @,整条语句必须完全遵循新 OpenSQL 语法规则:
|
||
- **字段列表必须逗号分隔**(旧式空格分隔报错):`SELECT carrid, connid, fldate FROM sflight`
|
||
- **INTO 子句前置**(在 FROM/WHERE 之前):`SELECT f1, f2 FROM tab INTO TABLE @lt_data WHERE ...`
|
||
- 旧式写法 `SELECT carrid connid fldate FROM sflight INTO TABLE lt_data`(无逗号)在全 @ 场景下报错
|
||
|
||
**验证示例(ZBC400_REVIEW_DEMO 2026-08-07 实测,syntax-check 全绿)**:
|
||
```abap
|
||
" ✅ 正确 — 新 OpenSQL 全 @:字段逗号分隔 + INTO 前置 + 全部 @
|
||
SELECT carrid, connid, fldate, seatsmax, seatsocc
|
||
FROM sflight
|
||
INTO TABLE @gt_result
|
||
WHERE carrid IN @s_carrid
|
||
AND fldate IN @s_date.
|
||
|
||
" ❌ 同语句 INTO 不带 @:When escaped, all host variables must be escaped using @
|
||
" ❌ 字段无逗号(旧式空格分隔):If host variables are escaped using @, new OpenSQL must used
|
||
```
|
||
|
||
**经验**:评审/优化代码时,只要目标系统是 7.40 SP05+ 且采用 @ 风格,直接按新 OpenSQL 规范写(字段逗号分隔 + INTO 前置 + 全 @),一次通过。质检判断"INTO TABLE 目标是豁免位置"**不成立**(2026-08-07 实测推翻),@ 必须全局一致。
|