# Oracle Jump Query Skill 通过中转服务查询远程 Oracle 数据库的 AI 技能,支持存储过程分析、表结构查询、数据权限控制。 ## 架构 ``` 用户/AI → 中转服务 (:6357) → WebSocket → Agent → Oracle 数据库 ``` - **中转服务**:转发 HTTP 请求到数据库服务器的 Agent - **Agent**:部署在数据库服务器,通过 WebSocket 连接中转服务,无需开放数据库端口 - **安全**:数据库服务器仅需出站 WebSocket 连接,防火墙友好 ## 环境要求 - Python 3.6+ - `pip install requests` ## 维护来源 本 skill 的 Git 地址: ```text 私有主库:https://gitea.momozhua.site/qiangayi/oracle-jump-query 公开镜像:https://gitea.momozhua.site/qiangayi/oracle-jump-query-public ``` 开发和发布使用私有主库;每次推送私有 Git 后必须同步更新无历史公共镜像,新用户可从公共镜像下载。同步前必须检查敏感文件并完成测试。`C:\Users\qiang\.codex\skills\oracle-jump-query` 是安装后的运行目录,不作为长期源码目录。 ## 快速开始 更多面向日常使用的问法和操作流程,见 [操作示例](docs/操作示例.md)。 ### 1. 配置 编辑 `scripts/config.json`: ```json { "transit_url": "https://ts.henlo.net", "server_id": "server-001", "access_token": "", "expires_at": "" } ``` 先登录中转机后再查询: ```bash python oracle_skill.py login [clientCode] python oracle_skill.py status ``` `secretKey` 只用于登录请求,不会保存到本地配置文件。`clientCode` 是客户服务器编号,非必填;不传时中转机会默认选择 BOS 返回的第一个可用 client。登录成功后本地仅保存中转机签发的 `access_token`、过期时间和可访问 client 列表。 同一个 `secretKey` 同时只允许一个设备在线。另一台设备重新登录后,当前设备的 token 会立即失效,需要重新执行 `login [clientCode]`。 ### 2. 运行交互模式 ```bash cd scripts python oracle_skill.py ``` ### 3. 运行指定命令 ```bash # 分析存储过程 python oracle_skill.py analyze bosnds3 M_RETAIL_SUBMIT # 查询表结构 python oracle_skill.py describe bosnds3 xcx_so # 执行 SELECT 查询:生产表必须带业务过滤条件和行数限制 python oracle_skill.py query "SELECT * FROM M_RETAIL WHERE BILLDATE = 20260501 AND ROWNUM <= 20" # 获取用户数据权限 python oracle_skill.py perm 940 12983 ``` ## 命令列表 | 命令 | 说明 | 示例 | |------|------|------| | `analyze ` | 完整分析存储过程(源码+依赖+表+触发器) | `analyze bosnds3 M_RETAIL_SUBMIT` | | `list ` | 列出 schema 下所有存储过程 | `list bosnds3` | | `source ` | 获取存储过程源码 | `source bosnds3 M_RETAIL_SUBMIT` | | `deps ` | 获取依赖(表/存储过程) | `deps bosnds3 M_RETAIL_SUBMIT` | | `describe ` | 查询表结构(列、类型、索引、行数) | `describe bosnds3 xcx_so` | | `query ` | 执行 SELECT 查询(仅支持 SELECT;生产表必须带过滤条件和行数限制) | `query SELECT * FROM M_RETAIL WHERE BILLDATE=20260501 AND ROWNUM<=20` | | `tablespace / tablespaces` | 查询表空间使用情况 | `tablespace` | | `perm ` | 查询用户数据权限 | `perm 940 12983` | | `qperm ` | 带权限过滤的查询 | `qperm 940 12983 SELECT * FROM M_OTHER_INOUT` | | `login [clientCode]` | 登录中转机 + 选择客户服务器,clientCode 非必填 | `login mykey HENLO` | | `logout` | 登出中转机并清除本地 token | `logout` | | `status` | 查看中转机登录状态 + 当前 client | `status` | | `switch ` | 按 code 或名称切换 client;找不到时自动刷新 client 列表 | `switch HENLO` | | `clients` | 无感刷新当前用户最新授权的 client 列表及在线状态(只使用当前登录 token) | `clients` | | `inspection_report [clientCode] [--json] [--html [path]] [--markdown [path]]` | 生成服务器巡检报告并归档,默认导出固定格式 HTML,可同时导出 Markdown | `inspection_report HENLO --markdown` | | `inspection_latest [clientCode] [--refresh] [--json] [--html [path]] [--markdown [path]]` | 查看最近归档巡检报告并默认导出 HTML;加 `--refresh` 时重新生成 | `inspection_latest HENLO --refresh --markdown` | | `inspection_get [--json] [--html [path]] [--markdown [path]]` | 按归档 ID 查看历史巡检报告并默认导出 HTML | `inspection_get 123 --markdown` | | `agent_update [clientCode] [timeout]` | 触发客户 Agent 自动更新,升级包由 Agent 从 OSS 下载 | `agent_update HENLO 300` | | `log_info [--client code]` | 验证服务器绝对日志路径和文件元数据 | `log_info "D:\logs\app.log" --client AHMW --json` | | `log_tail [--client code]` | 有界读取日志末尾内容 | `log_tail "D:\logs\app.log" --client AHMW --lines 200` | | `log_search ` | 在 Agent 本机按关键词或正则流式搜索日志 | `log_search "D:\logs\app.log" ERROR --client AHMW --json` | | `log_enable [clientCode]` / `log_disable [clientCode]` | 持久化开启或关闭目标客户日志分析 | `log_enable AHMW` | | `discover [schema] [filter]` | 发现核心业务表 | `discover bosnds3 M_%` | | `nl2sql ` | 自然语言转 SQL | `nl2sql bosnds3 查询花都二店5月销售额` | | `servers` | 列出在线 Agent | `servers` | | `health` | 检查中转服务状态 | `health` | | `capabilities --json` | 获取版本和命令定义(供程序调用) | `capabilities --json` | ## 生产查询限制 查询业务表时一定要带条件查询,不要直接查询整表。生产环境中业务表通常数据量很大,无条件 `SELECT * FROM
` 可能返回大量结果、拖慢 Agent 或影响数据库。 建议: - 必须包含 `WHERE` 条件,优先使用日期、单号、门店、客户、状态、主键等业务过滤条件。 - 必须加 `ROWNUM <= N` 或分页限制。 - 用户没有提供条件时,先追问日期、单号、门店等范围;不要直接查整表。 - 只想了解字段时,优先使用 `describe`、`AD_TABLE`、`AD_COLUMN`。 推荐: ```sql SELECT * FROM M_RETAIL WHERE BILLDATE = 20260501 AND STATUS = '2' AND ROWNUM <= 20 ``` 不要这样查: ```sql SELECT * FROM M_RETAIL ``` ### 品小二中文条件 品小二环境存在已知字符集转换问题,中文条件直接写成 `LIKE '%中文%'` 可能返回 0 行。查询中文值时使用 Oracle `UNISTR` Unicode 转义,例如: ```sql SELECT ID, NAME, DESCRIPTION FROM AD_TABLE WHERE DESCRIPTION LIKE '%' || UNISTR('\96F6\552E\5355') || '%' AND ROWNUM <= 20 ``` 直接中文字面量查不到时,先用 `UNISTR` 形式重试;这条是品小二的客户级兼容规则。其他 client 若已验证直接中文字面量可用,不必强制改写,但 `UNISTR` 可作为跨环境复用和避免传输编码转换的通用兜底。 ## 常用业务对象说明 - “商品”“款号”通常指 `M_PRODUCT` 表。 - “条码”“SKU”通常指 `M_PRODUCT_ALIAS` 表。 - 查询条码/SKU 时,首查 `M_PRODUCT_ALIAS.NO` 字段。 - 款号和条码是一对多关系:一个款号可以对应多个条码/SKU。 - 商品明细里常见的 `M_PRODUCT_ID`、`M_PRODUCTALIAS_ID`、`M_ATTRIBUTESETINSTANCE_ID` 分别对应款号、条码、色码属性 ASI。 - `M_ATTRIBUTESETINSTANCE` 的 `VALUE1`、`VALUE1_CODE`、`VALUE1_ID` 对应颜色名称、颜色编号、颜色表 `M_COLOR.ID`;`VALUE2`、`VALUE2_CODE`、`VALUE2_ID` 对应尺码名称、尺码编号、尺码表 `M_SIZE.ID`。 - 涉及库存查询时,通常查询 `V_FA_STORAGE` 视图。 - `V_FA_STORAGE` 数据量很大,必须通过店仓 + 款号/条码条件查询,不要直接查整张库存视图。 库存查询建议: - 用户只说“查库存”但没有给出店仓或款号/条码时,先追问条件。 - 通过款号查库存时,围绕 `M_PRODUCT` 找商品。 - 通过条码/SKU 查库存时,优先用 `M_PRODUCT_ALIAS.NO` 找条码,再关联到商品。 - 通过颜色/尺码查商品明细或库存时,优先用 `M_ATTRIBUTESETINSTANCE` 的 `VALUE1_ID` / `VALUE2_ID` 或 `VALUE1_CODE` / `VALUE2_CODE` 过滤。 - 查询 `V_FA_STORAGE` 时必须加店仓条件、款号/条码条件和 `ROWNUM` 或分页限制。 ## 应用场景 ### 场景一:分析存储过程业务逻辑 分析 `M_RETAIL_SUBMIT` 存储过程: ``` 输入:python oracle_skill.py analyze bosnds3 M_RETAIL_SUBMIT 输出: - 完整源码(PL/SQL) - 依赖的表、视图、嵌套存储过程 - 涉及的表结构(列名、类型、长度) - 触发器列表 ``` ### 场景二:查询数据字典 通过 `AD_TABLE`、`AD_COLUMN` 查询表和字段的业务含义: ```sql -- 查询 M_RETAIL 的字段描述 SELECT DBNAME, NAME, DESCRIPTION, COLTYPE FROM AD_COLUMN WHERE AD_TABLE_ID = (SELECT ID FROM AD_TABLE WHERE NAME = 'M_RETAIL') ORDER BY ORDERNO ``` 也可以通过 BOS 元数据体系分析系统菜单、模块目录和业务表结构。`AD_TABLE_TEXT` 过程显示 BOS 的系统地图主要由 `AD_SUBSYSTEM -> AD_TABLECATEGORY -> AD_ACCORDION -> AD_TABLE -> AD_COLUMN / AD_REFBYTABLE / AD_ACTION` 驱动,报表模板由 `AD_CXTAB` 相关表维护,权限挂载点在 `DIRECTORY`。 ```sql SELECT ss.NAME AS SUBSYSTEM, tc.NAME AS TABLE_CATEGORY, ac.NAME AS ACCORDION, t.ID AS AD_TABLE_ID, t.NAME AS TABLE_NAME, t.DESCRIPTION, t.PROC_SUBMIT, d.NAME AS DIRECTORY_NAME FROM AD_TABLE t LEFT JOIN AD_TABLECATEGORY tc ON tc.ID = t.AD_TABLECATEGORY_ID LEFT JOIN AD_SUBSYSTEM ss ON ss.ID = tc.AD_SUBSYSTEM_ID LEFT JOIN AD_ACCORDION ac ON ac.ID = t.AD_ACCORDION_ID LEFT JOIN DIRECTORY d ON d.ID = t.DIRECTORY_ID WHERE t.NAME LIKE '%关键词%' OR t.DESCRIPTION LIKE '%关键词%' ORDER BY ss.NAME, tc.ORDERNO, ac.ORDERNO, t.ORDERNO, t.NAME ``` ### 场景三:带权限过滤的查询 普通用户查询时自动拼接权限条件(如按门店过滤): ``` 输入:python oracle_skill.py qperm 940 12983 SELECT * FROM M_OTHER_INOUT 自动拼接:C_STORE_ID IN(...) WHERE 条件 输出:仅返回用户有权限查看的数据 ``` ## 数据权限模型 数据库内置 `get_userspermsql` 函数: ```sql FUNCTION get_userspermsql( p_users_id NUMBER, -- 用户ID p_tableid NUMBER, -- 表ID (AD_TABLE.ID) p_col VARCHAR2 -- 字段名,可为NULL ) RETURN CLOB -- 返回权限过滤SQL ``` 返回值示例: - 空字符串:全权限(无需过滤) - `C_STORE_ID IN(1,2,3)`:仅可查看指定门店 ## 常见问题 | 问题 | 解决方法 | |------|----------| | 无法连接中转服务 | 检查 `config.json` 中的 `transit_url` 地址和端口 | | agent not found | 确认 Agent 已启动并连接成功 | | 请求超时 | Agent 可能卡住,增大 `timeout` 参数 | ## 相关项目 - [恒诺云打印 Print_Tool](https://gitee.com/qiangayi/henlo_mid) - .NET 10 升级项目 - [Henlo_Mid 通用接口](https://gitee.com/qiangayi/henlo_mid) - 企业内部系统集成 ## License MIT ## 服务器巡检报告 当用户询问“给我 HENLO 的服务器体检报告 / 巡检报告 / 运维体检报告 / 备份和资源情况”时,统一调用新版巡检入口: ```bash python scripts/oracle_skill.py inspection_report HENLO python scripts/oracle_skill.py inspection_report HENLO --markdown python scripts/oracle_skill.py inspection_latest HENLO --refresh --markdown ``` 巡检命令成功后默认把固定格式 HTML 写入 `outputs/`。增加 `--markdown`(或 `--md`)会同时生成 Markdown;`--html` 和 `--markdown` 后均可指定自定义输出路径。 HTML 导出使用固定模板,CSS、章节顺序和表格结构保持不变,只替换报告编号、采集时间、指标值、告警和明细行。不传路径时写入 skill 目录下的 `outputs/`。 当前报告支持服务器 IP、系统版本、启动时间/运行时长、关键进程、TCP 连接统计,以及 Oracle ACTIVE/总会话数和 Buffer/Library Cache 命中率。AWR 已记录在未来开发计划中,当前版本不执行 AWR 采集;详细边界见 `references/oracle-ops-and-checkup.md`。 ## Oracle 日常运维监控 单项监控: ```bash python scripts/oracle_skill.py ops active_slow_sql HENLO python scripts/oracle_skill.py ops blocking_locks HENLO python scripts/oracle_skill.py ops ora_errors HENLO ``` 统一日报: ```bash python scripts/oracle_skill.py ops_report HENLO ``` `clientCode` 可省略,不传时使用当前登录 client。第一版支持的监控项包括:`active_slow_sql`、`history_top_sql`、`fullscan_sql`、`plan_heavy_sql`、`blocking_locks`、`long_transactions`、`inactive_sessions`、`datafiles`、`undo`、`memory`、`io_waits`、`background_process`、`ora_errors`、`invalid_objects`、`tablespace`。 涉及 `v$`、`dba_`、AWR、alert log 等 SYS/DBA 权限视图时,Agent 会优先调用 `SYS.HENLO_ORA_MONITOR`,如果不可用则自动尝试当前登录账号下的 `HENLO_ORA_MONITOR`。如果两个函数都不存在或未授权,命令会输出两种安装方案:有 SYS 账号时安装到 SYS 并授权;没有 SYS 账号但当前登录账号已有系统视图查询权限时,直接安装到当前账号。 生成巡检报告时,Skill 会先执行 SYS 函数版本与授权预检。预检失败后会读取目标 Agent 的实际 Oracle schema,并把完整 SQL 中的授权账号自动替换为该 schema;输出中不得保留 `` 占位符。无法取得 schema 时停止生成报告并提示检查 Agent 配置。 ## 新增业务记录 SQL 生成规则 业务单据的商品明细有新增功能、需要通过商品新增输入框输入条码录入时,`AD_TABLE.CLASSNAME` 配置为 `nds.schema.AttributeDetailSupportTableImpl`。明细通常有商品 ID `M_PRODUCT_ID`、条码 ID `M_PRODUCTALIAS_ID`、ASI ID `M_ATTRIBUTESETINSTANCE_ID`;ASI 字段读写规则一般为 `1100000000`,只在新增时可见。字段名称和明细新增动作需核实,详细规则见 [商品明细的条码新增配置](./references/query-and-business-rules.md#业务单据商品明细的条码新增配置)。 新建 BOS 业务单据表单时,在八个基础字段和主键之上通常还需 `DOCNO`、`STATUS`、提交时间、提交人;`ISACTIVE` 已在基础字段中。表级读写规则默认 `MDQSV`。`DOCNO` 维护编号生成器,读写方式为“单据编号”;`STATUS`、`ISACTIVE` 使用“下拉框选项”,选项名称分别为 `STATUS`、`YESNO`,字段翻译器均为 `nds.web.alert.LimitValueAlerter`,默认值分别为 `1`、`Y`。三个字段的读写打印规则均为 `0010111111`,保留前导零。提交人和提交时间由提交动作维护;详细规则见 [业务单据表单默认配置](./references/query-and-business-rules.md#bos-新建业务单据表单默认配置)。 本 skill 默认只读,不直接执行写库操作;当需要分析或生成新增业务记录 SQL 示例时,遵守以下 BOS 默认取值规则: - 新增记录主键 `ID` 使用 `get_sequences('<表名称>')`。 - 如果表存在 `DOCNO` 字段,先到 `AD_COLUMN` 查询该字段的 `SEQUENCENAME`。 - 取单号函数为 `Get_SequenceNo('', AD_CLIENT_ID)`;默认 `CODE` 取该单据 `DOCNO` 字段对应的 `AD_COLUMN.SEQUENCENAME` 值,第二个参数取单据实际的 `AD_CLIENT_ID`,确认是 `37` 时才写 `37`。配置为空时不猜测 `CODE`,特殊业务按实际配置和过程逻辑核实;只生成 SQL 示例,不通过查询通道调用取号函数。 - 取号 `CODE` 的定义在 `AD_SEQUENCE` 表,分析编号规则时沿 `DOCNO -> AD_COLUMN.SEQUENCENAME -> AD_SEQUENCE` 核实。 - 如果表存在 `AD_CLIENT_ID` 字段,默认值为 `37`。 - 如果表存在 `AD_ORG_ID` 字段,默认值为 `27`。 - 子表 `AD_CLIENT_ID`、`AD_ORG_ID` 默认继承父表对应字段值。 - 新增业务表单时,如果表存在 `STATUS`、`STATUSERID`、`STATUSTIME` 字段,通常只设置 `STATUS='1'`,不对 `STATUSERID`、`STATUSTIME` 赋值。 - `STATUS='1'` 表示草稿/未提交;提交相关字段通常由提交逻辑维护。 - 如果用户提到“提交”,通常指该表在 `AD_TABLE.PROC_SUBMIT` 中配置的提交存储过程。 - 生成提交 SQL 或说明提交流程时,如果已知 `userId`,调用 `AD_TABLE.PROC_SUBMIT` 前需要先更新主单据修改人和修改时间,再调用提交存储过程;修改人、修改时间字段名必须先通过 `AD_COLUMN` 或表结构确认,不要凭经验硬写字段名。 - 分析 BOS 业务表时,同时查看 `AD_TABLE` 的表单事件过程:`HAS_TRIG_BD='Y'` 时 `TRIG_BD` 为删除前触发过程(bd),`HAS_TRIG_AC='Y'` 时 `TRIG_AC` 为新增后触发过程(ac),`HAS_TRIG_AM='Y'` 时 `TRIG_AM` 为修改后触发过程(am)。 ## 字段值域映射规则 当 `AD_COLUMN` 中某个字段的 `OBTAINMANNER` 值为 `select` 时,该字段的可选值不应直接猜测,需要通过 `AD_LIMITVALUE_GROUP_ID` 查询子表 `AD_LIMITVALUE`,取得“数据库实际值”和“显示值”的映射关系。 示例:`XH_ORDER_FTP.BILLTYPE` 的显示值“券核销”,对应实际入库值是 `VOU_USED`。当用户说“类型为券核销”时,生成查询条件或新增记录 SQL 应使用实际值: ```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 ``` ## Agent 版本查询 自然语言提示词:查询所有客户的 Agent 版本号;或查询 HENLO、RENBEN 的 Agent 版本号。 ```powershell python scripts/oracle_skill.py version agent HENLO RENBEN --json python scripts/oracle_skill.py version agent --all --json ``` ## 从 Git 更新 Skill ### 每日自动更新与使用记录 CLI 启动时记录最后使用时间;按运行电脑本地日期,每个使用日首次启动自动 `fetch origin main`,检测到新版本时仅在 `main` 分支执行快进安装,并重新启动当前命令使用新版本。同一天后续启动不重复抓取;未使用的日期不运行后台任务。每次开始应用 Skill 时先运行 `python scripts/oracle_skill.py capabilities --json`,使只参考业务知识的任务也触发检测。 本机状态文件为 `scripts/update-state.json`:`last_used_at` 记录最后使用时间,`last_checked_at` / `last_check_date` 记录检测时间和日期,`status` 记录 `checking`、`up_to_date`、`updated`、`update_blocked`、`check_failed` 或 `not_git`;检测完成时可包含本机和远端提交 ID。状态、锁和临时文件不提交 Git,不保存 token、密钥、SQL 或查询结果。 自动更新保留本机 `config.json` 和 `scripts/config.json`;源码有未提交修改、存在暂存修改、分支分叉或配置冲突时暂停安装并继续原命令。抓取超时为 10 秒,认证和网络失败不阻止业务命令,也不在当天每次调用时重试;可手动执行 `git pull --ff-only origin main` 重试。提示写入 stderr,stdout 的 JSON 输出不受影响。Git checkout 使用自己的 `origin`,私有和公共安装均可使用;无 `.git` 的下载目录只记录使用时间。 Skill 仅通过 Gitea Git 仓库更新,不使用 OSS 或 `skill_update` 命令。源码仓库完成修改并推送私有库后,必须同步更新无历史公共镜像;随后在已安装目录执行: ```powershell cd C:\Users\qiang\.codex\skills\oracle-jump-query git pull --ff-only origin main python scripts/oracle_skill.py capabilities --json ``` 在线 Agent 直接确认当前版本;离线客户返回最后一次心跳版本和离线状态。