Files
oracle-jump-query-public/README.md
T

347 lines
15 KiB
Markdown
Raw 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.
# 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
```
开发和发布使用私有主库;新用户可从公开镜像下载经人工确认的无历史快照。`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 <secretKey> [clientCode]
python oracle_skill.py status
```
`secretKey` 只用于登录请求,不会保存到本地配置文件。`clientCode` 是客户服务器编号,非必填;不传时中转机会默认选择 BOS 返回的第一个可用 client。登录成功后本地仅保存中转机签发的 `access_token`、过期时间和可访问 client 列表。
同一个 `secretKey` 同时只允许一个设备在线。另一台设备重新登录后,当前设备的 token 会立即失效,需要重新执行 `login <secretKey> [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 <schema> <proc>` | 完整分析存储过程(源码+依赖+表+触发器) | `analyze bosnds3 M_RETAIL_SUBMIT` |
| `list <schema>` | 列出 schema 下所有存储过程 | `list bosnds3` |
| `source <schema> <proc>` | 获取存储过程源码 | `source bosnds3 M_RETAIL_SUBMIT` |
| `deps <schema> <proc>` | 获取依赖(表/存储过程) | `deps bosnds3 M_RETAIL_SUBMIT` |
| `describe <schema> <table>` | 查询表结构(列、类型、索引、行数) | `describe bosnds3 xcx_so` |
| `query <SQL>` | 执行 SELECT 查询(仅支持 SELECT;生产表必须带过滤条件和行数限制) | `query SELECT * FROM M_RETAIL WHERE BILLDATE=20260501 AND ROWNUM<=20` |
| `tablespace / tablespaces` | 查询表空间使用情况 | `tablespace` |
| `perm <userId> <tableId>` | 查询用户数据权限 | `perm 940 12983` |
| `qperm <userId> <tableId> <SQL>` | 带权限过滤的查询 | `qperm 940 12983 SELECT * FROM M_OTHER_INOUT` |
| `login <secretKey> [clientCode]` | 登录中转机 + 选择客户服务器,clientCode 非必填 | `login mykey HENLO` |
| `logout` | 登出中转机并清除本地 token | `logout` |
| `status` | 查看中转机登录状态 + 当前 client | `status` |
| `switch <clientCode|clientName>` | 按 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 <id> [--json] [--html [path]] [--markdown [path]]` | 按归档 ID 查看历史巡检报告并默认导出 HTML | `inspection_get 123 --markdown` |
| `agent_update [clientCode] [timeout]` | 触发客户 Agent 自动更新,升级包由 Agent 从 OSS 下载 | `agent_update HENLO 300` |
| `discover [schema] [filter]` | 发现核心业务表 | `discover bosnds3 M_%` |
| `nl2sql <schema> <question>` | 自然语言转 SQL | `nl2sql bosnds3 查询花都二店5月销售额` |
| `servers` | 列出在线 Agent | `servers` |
| `health` | 检查中转服务状态 | `health` |
| `capabilities --json` | 获取版本和命令定义(供程序调用) | `capabilities --json` |
## 生产查询限制
查询业务表时一定要带条件查询,不要直接查询整表。生产环境中业务表通常数据量很大,无条件 `SELECT * FROM <table>` 可能返回大量结果、拖慢 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
```
## 常用业务对象说明
- “商品”“款号”通常指 `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;输出中不得保留 `<AGENT_SCHEMA>` 占位符。无法取得 schema 时停止生成报告并提示检查 Agent 配置。
## 新增业务记录 SQL 生成规则
本 skill 默认只读,不直接执行写库操作;当需要分析或生成新增业务记录 SQL 示例时,遵守以下 BOS 默认取值规则:
- 新增记录主键 `ID` 使用 `get_sequences('<表名称>')`。
- 如果表存在 `DOCNO` 字段,先到 `AD_COLUMN` 查询该字段的 `SEQUENCENAME`。
- 如果 `SEQUENCENAME` 有值,`DOCNO` 使用 `Get_SequenceNo('<SEQUENCENAME>', 37)`。
- 如果表存在 `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
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 直接确认当前版本;离线客户返回最后一次心跳版本和离线状态。