351 lines
16 KiB
Markdown
351 lines
16 KiB
Markdown
# 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` |
|
||
| `log_info <path> [--client code]` | 验证服务器绝对日志路径和文件元数据 | `log_info "D:\logs\app.log" --client AHMW --json` |
|
||
| `log_tail <path> [--client code]` | 有界读取日志末尾内容 | `log_tail "D:\logs\app.log" --client AHMW --lines 200` |
|
||
| `log_search <path> <pattern...>` | 在 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 <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 直接确认当前版本;离线客户返回最后一次心跳版本和离线状态。
|