# 生产查询限制与常用业务规则 > 本文件由 SKILL.md 整理拆分而来,保留原说明内容。 ## 生产查询限制 直接查询业务表时,必须带明确过滤条件,不要直接查询整表。生产环境数据量很大,`SELECT * FROM ` 这类无条件查询可能返回大量数据、拖慢 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 ``` ## 常用业务对象说明 当用户使用商品、款号、条码、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 元数据。 ## 新增业务记录 SQL 生成规则 当用户要求分析或生成新增业务表记录的 SQL 示例时,仍然保持只读安全边界:skill 可以生成 SQL 和说明,但不能直接通过查询通道执行 INSERT、UPDATE、DELETE、MERGE、DDL 等写操作。 生成新增记录 SQL 时遵守以下默认规则: - 主表或子表新增记录的主键 `ID` 使用 `get_sequences('<表名称>')` 取值。 - 如果目标表存在 `DOCNO` 字段,先查询 `AD_COLUMN` 中该字段是否配置 `SEQUENCENAME` 单据编号生成器。 - 如果 `DOCNO` 对应的 `SEQUENCENAME` 有值,则单据编号使用 `Get_SequenceNo('', 37)` 取值。 - 如果目标表存在 `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' ``` ## 字段值域映射规则(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 = ORDER BY ORDERNO, ID ```