Files

234 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生产查询限制与常用业务规则
> 本文件由 SKILL.md 整理拆分而来,保留原说明内容。
## 生产查询限制
直接查询业务表时,必须带明确过滤条件,不要直接查询整表。生产环境数据量很大,`SELECT * FROM <table>` 这类无条件查询可能返回大量数据、拖慢 Agent 或影响数据库。
生成或执行 `query` / `qperm` SQL 时遵守:
- 必须有 `WHERE` 条件,优先使用日期、单号、门店、客户、状态、主键等业务过滤条件。
- 必须加行数限制,例如 `ROWNUM <= 20`;需要分页时分批查询。
- 不要为了“先看看数据”执行无条件整表查询。
- 统计查询也要限定业务范围,例如日期区间、单据状态、门店范围。
- 如果用户没有给出过滤条件,先追问条件,或先用 `describe` / `AD_COLUMN` / `AD_TABLE` 查询结构和字段含义。
推荐示例:
```sql
SELECT *
FROM M_RETAIL
WHERE BILLDATE = 20260501
AND STATUS = '2'
AND ROWNUM <= 20
```
避免示例:
```sql
SELECT * FROM M_RETAIL
```
## 中文条件与字符集兼容
品小二环境存在已知字符集转换问题:通过 Skill 查询时,中文字符串直接写成 `LIKE '%中文%'`,或直接把中文写入 `=` 等值条件,可能返回 0 行,即使数据库中存在匹配记录。
查询品小二中的中文值时,优先使用 Oracle `UNISTR` 和 Unicode 转义,将 SQL 中的中文条件保持为 ASCII。例如“零售单”的 Unicode 编码为 `96F6 552E 5355`,应写成:
```sql
SELECT ID, NAME, DESCRIPTION
FROM AD_TABLE
WHERE DESCRIPTION LIKE '%' || UNISTR('\96F6\552E\5355') || '%'
AND ROWNUM <= 20
```
精确匹配同样适用,例如“品小二”可写成 `= UNISTR('\54C1\5C0F\4E8C')`。中文条件直接查询返回 0 行时,先改用 `UNISTR` 形式重试,再判断数据是否确实不存在。对其他 client,如果直接中文字面量已验证可用,不必强制改写;但在需要跨客户复用 SQL,或希望让 SQL 文本保持 ASCII、避免客户端/HTTP/命令行传输转换时,`UNISTR` 也是有帮助的通用兜底。该函数返回 Oracle national character set,面对超大表的 `VARCHAR2` 索引条件时仍应关注执行计划;无论使用哪种写法,仍须遵守生产查询的过滤条件和行数限制。
## 常用业务对象说明
当用户使用商品、款号、条码、SKU、库存等业务词时,默认按以下对象理解:
- “商品”“款号”通常指 `M_PRODUCT` 表。
- “条码”“SKU”通常指 `M_PRODUCT_ALIAS` 表。
- 查询条码/SKU 时,首查 `M_PRODUCT_ALIAS.NO` 字段。
- 款号和条码是一对多关系:一个 `M_PRODUCT` 可以对应多条 `M_PRODUCT_ALIAS`。
- 商品明细表中常见的三个商品维度字段:
- `M_PRODUCT_ID`:款号 / 商品,关联 `M_PRODUCT.ID`。
- `M_PRODUCTALIAS_ID`:条码 / SKU,关联 `M_PRODUCT_ALIAS.ID`。
- `M_ATTRIBUTESETINSTANCE_ID`:色码属性 ASI,关联 `M_ATTRIBUTESETINSTANCE.ID`。
- `M_ATTRIBUTESETINSTANCE` 用于记录商品色码属性:
- `VALUE1`:颜色名称。
- `VALUE1_CODE`:颜色编号。
- `VALUE1_ID`:颜色表 ID,关联 `M_COLOR.ID`。
- `VALUE2`:尺码名称。
- `VALUE2_CODE`:尺码编号。
- `VALUE2_ID`:尺码表 ID,关联 `M_SIZE.ID`。
- 如果涉及库存查询,通常查询 `V_FA_STORAGE` 视图。
- `V_FA_STORAGE` 数据量很大,必须同时带店仓条件和款号/条码条件,不允许只查整张库存视图。
库存查询过滤规则:
- 店仓条件应优先使用门店、仓库、店仓 ID 或店仓编码等字段,先通过 `describe` 或 `AD_COLUMN` 确认实际字段名。
- 款号条件走 `M_PRODUCT`;条码/SKU 条件走 `M_PRODUCT_ALIAS`。
- 颜色、尺码、色码属性条件优先走 `M_ATTRIBUTESETINSTANCE`,再分别通过 `VALUE1_ID` 关联 `M_COLOR`、通过 `VALUE2_ID` 关联 `M_SIZE`。
- 通过条码查库存时,应先用 `M_PRODUCT_ALIAS.NO` 找到对应商品,再关联或过滤 `V_FA_STORAGE`。
- 必须加 `ROWNUM` 或分页限制;如果用户没有提供店仓或款号/条码,先追问,不要直接查询库存视图。
示例思路:
```sql
-- 伪示例:实际字段名需先 describe / AD_COLUMN 确认
SELECT *
FROM V_FA_STORAGE s
WHERE s.C_STORE_ID = :store_id
AND s.M_PRODUCT_ID = :product_id
AND ROWNUM <= 20
```
## BOS 新建表最小结构(仅生成 DDL)
按照 BOS 系统规则,为新建表生成结构 SQL 时,至少包含下面八个基础字段和 `ID` 主键。业务字段在此基础上增加,不要只列业务字段而漏掉基础字段。`TableName` 是表名占位符,生成具体方案时替换为用户确认的表名。
```sql
CREATE TABLE TableName (
ID NUMBER(10) NOT NULL,
AD_CLIENT_ID NUMBER(10),
AD_ORG_ID NUMBER(10),
OWNERID NUMBER(10),
CREATIONDATE DATE,
MODIFIERID NUMBER(10),
MODIFIEDDATE DATE,
ISACTIVE CHAR(1) DEFAULT 'Y' NOT NULL,
PRIMARY KEY (ID)
);
```
- “必须包含字段”不等于“所有字段非空”:本模板只有 `ID` 和 `ISACTIVE` 明确 `NOT NULL`,其余六个字段允许为空。
- `ID`、`AD_CLIENT_ID`、`AD_ORG_ID`、`OWNERID`、`MODIFIERID` 使用 `NUMBER(10)`;`CREATIONDATE`、`MODIFIEDDATE` 使用 `DATE`;`ISACTIVE` 使用 `CHAR(1)`,默认值为 `'Y'`。
- 不要把新增业务记录时的 `AD_CLIENT_ID=37`、`AD_ORG_ID=27` 或主键取号规则自动写成建表 `DEFAULT`;本最小模板只为 `ISACTIVE` 指定默认值,日期字段也不自动增加 `DEFAULT SYSDATE`。
- 这是新建表结构规则,不表示可以自动修改既有表。Skill 仅生成 DDL 并明确“未执行”,由用户或 DBA 确认后人工执行;不通过 `query` / `qperm` 建表,也不隐式写入 BOS 元数据。
## BOS 新建业务单据表单默认配置
新增 BOS 表单时,先判断是否为业务单据。通常包含 `DOCNO` 的表单可按业务单据理解,并结合实际用途核实;新建业务单据表单通常应包含 `DOCNO`、`STATUS`、`ISACTIVE`、提交时间和提交人。这些业务字段在上面的八个基础字段及 `ID` 主键之上补充,其中 `ISACTIVE` 已属于基础字段,不重复创建。本节是业务单据的默认约定,不要求所有基础资料表都增加单号或提交字段。
字段及 BOS 元数据配置:
| 字段 | 业务含义 | 读写方式 | 下拉框选项名称 | 字段翻译器 | 读写打印规则 | 默认值 |
| --- | --- | --- | --- | --- | --- | --- |
| `DOCNO` | 单据编号 | 单据编号 | 不适用 | 按目标环境单据编号配置核实 | `0010111111` | 按维护的单据编号生成器取号 |
| `STATUS` | 单据状态 | 下拉框选项 | `STATUS` | `nds.web.alert.LimitValueAlerter` | `0010111111` | `1` |
| `ISACTIVE` | 可用 | 下拉框选项 | `YESNO` | `nds.web.alert.LimitValueAlerter` | `0010111111` | `Y` |
| 提交时间 | 提交时间,常用字段名 `STATUSTIME` | 按目标表单配置核实 | 不适用 | 按实际配置核实 | 按实际配置核实 | 新增草稿时不赋值,由提交动作维护 |
| 提交人 | 提交人,常用字段名 `STATUSERID` | 按目标表单配置核实 | 不适用 | 按实际配置核实 | 按实际配置核实 | 新增草稿时不赋值,由提交动作维护 |
- `DOCNO` 必须维护单据编号生成器:`AD_COLUMN` 中该字段的 `SEQUENCENAME` 保存取号 CODE,CODE 的定义在 `AD_SEQUENCE`,取号表达式为 `Get_SequenceNo('<CODE>', AD_CLIENT_ID)`。生成器 CODE 按业务维护,不猜测具体名称,也不通过查询通道调用取号函数。
- `STATUS` 和 `ISACTIVE` 的字段翻译器配置位于 `AD_COLUMN`,值为 `nds.web.alert.LimitValueAlerter`。`ISACTIVE` 除选项名称为 `YESNO`、默认值为 `Y` 外,其余上述配置与 `STATUS` 相同;保留最小建表模板中的 `ISACTIVE CHAR(1) DEFAULT 'Y' NOT NULL`。
- 下拉框选项名称 `STATUS`、`YESNO` 是对应选项组名称,不是数据库实际值。生成具体元数据方案时,先定位目标环境的选项组,再用 `AD_COLUMN.AD_LIMITVALUE_GROUP_ID` 核实 `AD_LIMITVALUE` 的显示值与实际值,不猜测选项组 ID。读写方式为下拉框选项时,按目标环境核实 `OBTAINMANNER='select'` 等实际存储值。
- 所在表的读写规则默认是 `AD_TABLE.MASK='MDQSV'`,按该字符串维护:`M` 修改、`D` 删除、`Q` 查询、`S` 提交、`V` 作废。此默认值用于新建业务单据方案;分析既有表时仍以实际 `MASK` 为准。
- 表级读写规则 `MDQSV` 与字段级读写打印规则 `0010111111` 是不同配置。字段规则保留完整十位字符串及前导零,不转成整数,也不凭经验解释各位含义。
- 需要提交的业务单据必须包含提交时间和提交人,并核实 `AD_TABLE.PROC_SUBMIT` 对应提交逻辑。上述常用字段名、字段类型、关联方式和可空性需按目标环境或用户确认的方案确定;新增草稿只设 `STATUS='1'`,提交时由提交动作维护提交人和时间。
- 生成 BOS 元数据 SQL 时,先确认目标环境 `AD_COLUMN` 中“字段翻译器”“读写方式”“读写打印规则”“默认值”等配置项对应的实际列名,不凭中文标签猜测物理列名。建表 DDL 与表单元数据配置分别说明;这里仅记录默认规则并生成待人工确认的方案,不通过 Skill 查询通道创建表、维护生成器或写入 BOS 元数据。
## 业务单据商品明细的条码新增配置
业务单据的商品明细表有新增功能、需要通过商品新增输入框输入条码录入时,`AD_TABLE.CLASSNAME` 配置为 `nds.schema.AttributeDetailSupportTableImpl`。该实现类在 BOS 中表示商品明细支持这种条码新增输入方式;分析或生成商品明细方案时,应同时核实该明细表的新增功能和 `CLASSNAME`,不把它套用到所有明细表。
商品明细通常包含以下三个维度字段:
| 常用字段 | 业务含义 | 通常关联对象 | 默认配置说明 |
| --- | --- | --- | --- |
| `M_PRODUCT_ID` | 商品 ID / 款号 ID | `M_PRODUCT.ID` | 按目标表单实际配置核实 |
| `M_PRODUCTALIAS_ID` | 条码 ID / SKU ID,用户也可能简称 `m_productalias` | `M_PRODUCT_ALIAS.ID` | 生成 SQL 前确认实际字段名 |
| `M_ATTRIBUTESETINSTANCE_ID` | ASI ID / 色码属性 ID,简称 `asiid` | `M_ATTRIBUTESETINSTANCE.ID` | 字段读写规则一般为 `1100000000`,只在新增时可见 |
- `1100000000` 是 ASI 字段的读写规则,按完整十位字符串保存;业务含义为只在新增时可见,不直接沿用主单据 `DOCNO`、`STATUS`、`ISACTIVE` 的 `0010111111` 规则,也不自行推断其他位含义。
- 商品明细与主单据的关系先通过 `AD_REFBYTABLE` 核实,三个维度字段通过 `AD_COLUMN` 或实际表结构确认;条码字段常用名是 `M_PRODUCTALIAS_ID`,不能只凭用户简称生成不存在的 `M_PRODUCTALIAS` 列。
- 主单据默认 `MASK='MDQSV'` 不表示商品明细自动支持新增;明细的新增动作配置按其实际 `AD_TABLE.MASK` 核实,需要条码新增时再维护上述 `CLASSNAME` 和字段配置。
- 本节是 BOS 元数据和表单行为约定,仅用于分析或生成待人工确认的配置方案,不通过 Skill 查询通道写入 `AD_TABLE`、`AD_COLUMN` 或业务明细。
## 新增业务记录 SQL 生成规则
当用户要求分析或生成新增业务表记录的 SQL 示例时,仍然保持只读安全边界:skill 可以生成 SQL 和说明,但不能直接通过查询通道执行 INSERT、UPDATE、DELETE、MERGE、DDL 等写操作。
生成新增记录 SQL 时遵守以下默认规则:
- 主表或子表新增记录的主键 `ID` 使用 `get_sequences('<表名称>')` 取值。
- 如果目标表存在 `DOCNO` 字段,先查询 `AD_COLUMN` 中该字段是否配置 `SEQUENCENAME` 单据编号生成器。
- 取单号函数为 `Get_SequenceNo('<CODE>', AD_CLIENT_ID)`。一般情况下,`CODE` 取该单据 `DOCNO` 字段对应的 `AD_COLUMN.SEQUENCENAME` 值,第二个参数取单据实际的 `AD_CLIENT_ID`;这是默认业务约定,特殊业务以目标环境的实际配置和过程逻辑为准。
- `CODE` 的定义在 `AD_SEQUENCE` 表中。`AD_COLUMN.SEQUENCENAME` 是单据字段配置的取号 CODE;要理解编号规则,继续到 `AD_SEQUENCE` 核实该 CODE 对应的定义。先确认目标环境的表结构和字段含义,不凭经验假定关联字段或编号格式。
- 如果 `DOCNO` 对应的 `SEQUENCENAME` 有值,则生成 `Get_SequenceNo('<SEQUENCENAME>', <单据的 AD_CLIENT_ID>)` 作为单据编号表达式。仅当该单据的 `AD_CLIENT_ID` 确认为 `37` 时,第二个参数才写 `37`;子表使用继承父表的客户 ID。配置为空时不猜测 `CODE`,应继续核实取号逻辑。
- 取号函数可能推进编号状态,即使包装在 `SELECT` 中也不得通过 `query` / `qperm` 调用。这里只生成 SQL 示例,不实际取号。
- 如果目标表存在 `AD_CLIENT_ID` 字段,默认值使用 `37`。
- 如果目标表存在 `AD_ORG_ID` 字段,默认值使用 `27`。
- 子表的 `AD_CLIENT_ID` 和 `AD_ORG_ID` 默认取父表记录中对应字段值,不单独写固定值。
- 新增业务表单时,如果目标表存在 `STATUS`、`STATUSERID`、`STATUSTIME` 字段,通常只给 `STATUS` 赋默认值 `'1'`,不对 `STATUSERID`、`STATUSTIME` 赋值。
- `STATUS='1'` 表示草稿/未提交;提交人、提交时间等字段由提交动作或提交存储过程处理。
- 如果用户明确提到“提交”,通常不是直接把 `STATUS` 改成 `'2'`,而是应先查询 `AD_TABLE.PROC_SUBMIT`,按该表配置的提交存储过程理解提交逻辑。
- 生成提交 SQL 或说明提交流程时,如果已知 `userId`,调用 `AD_TABLE.PROC_SUBMIT` 前需要先更新主单据修改人和修改时间,再调用提交存储过程;修改人、修改时间字段名必须先通过 `AD_COLUMN` 或表结构确认,不要凭经验硬写字段名。
查询 `DOCNO` 编号生成器示例:
```sql
SELECT SEQUENCENAME
FROM AD_COLUMN
WHERE AD_TABLE_ID = (SELECT ID FROM AD_TABLE WHERE NAME = '<表名称>')
AND UPPER(DBNAME) = 'DOCNO'
AND ROWNUM <= 20
```
## 字段值域映射规则(AD_COLUMN / AD_LIMITVALUE)
当用户要求解释字段含义、生成查询条件、分析业务类型,或生成新增业务记录 SQL 示例时,如果目标字段在 `AD_COLUMN` 中的 `OBTAINMANNER` 值为 `select`,必须继续通过 `AD_LIMITVALUE_GROUP_ID` 查询 `AD_LIMITVALUE`,拿到显示值与数据库实际值的映射关系。
关键规则:
- `AD_COLUMN.OBTAINMANNER = 'select'` 表示该字段是受限值列表。
- `AD_COLUMN.AD_LIMITVALUE_GROUP_ID` 关联 `AD_LIMITVALUE.AD_LIMITVALUE_GROUP_ID`。
- 用户通常说的是显示值,例如“券核销”。
- SQL 查询条件和新增记录 SQL 必须使用数据库实际值,例如 `VOU_USED`。
- 不要把显示值直接写入业务表字段,除非 `AD_LIMITVALUE` 查询结果证明显示值就是实际值。
示例:`XH_ORDER_FTP.BILLTYPE` 字段,当显示值为“券核销”时,对应的数据库实际值是 `VOU_USED`。因此用户说“类型为券核销”时,应生成:
```sql
XH_ORDER_FTP.BILLTYPE = 'VOU_USED'
```
查询字段值域映射模板:
```sql
SELECT c.DBNAME,
c.NAME,
c.OBTAINMANNER,
c.AD_LIMITVALUE_GROUP_ID,
v.VALUE,
v.NAME AS DISPLAY_NAME
FROM AD_COLUMN c
LEFT JOIN AD_LIMITVALUE v ON v.AD_LIMITVALUE_GROUP_ID = c.AD_LIMITVALUE_GROUP_ID
WHERE c.AD_TABLE_ID = (SELECT ID FROM AD_TABLE WHERE NAME = '<表名称>')
AND UPPER(c.DBNAME) = UPPER('<字段名>')
ORDER BY v.ORDERNO, v.ID
```
使用时先查字段:
```sql
SELECT ID, DBNAME, NAME, DESCRIPTION, OBTAINMANNER, AD_LIMITVALUE_GROUP_ID
FROM AD_COLUMN
WHERE AD_TABLE_ID = (SELECT ID FROM AD_TABLE WHERE NAME = 'XH_ORDER_FTP')
AND UPPER(DBNAME) = 'BILLTYPE'
```
如果 `OBTAINMANNER='select'` 且 `AD_LIMITVALUE_GROUP_ID` 有值,再查:
```sql
SELECT VALUE, NAME AS DISPLAY_NAME
FROM AD_LIMITVALUE
WHERE AD_LIMITVALUE_GROUP_ID = <AD_LIMITVALUE_GROUP_ID>
ORDER BY ORDERNO, ID
```