chore: publish secure public mirror
This commit is contained in:
@@ -0,0 +1,692 @@
|
||||
---
|
||||
name: oracle-jump-query
|
||||
description: Oracle 跳板查询技能。通过中转服务查询远程 Oracle 数据库的元数据(存储过程源码、依赖、表结构、触发器、直接查表),连接数据库为只读,禁止任何写操作。当用户需要分析 Oracle 存储过程、查找依赖表、查询表结构、查看业务逻辑时触发。
|
||||
---
|
||||
|
||||
# Oracle 跳板查询
|
||||
|
||||
> **版本:v1.5.8** · [更新日志](./CHANGELOG.md)
|
||||
|
||||
## 概述
|
||||
|
||||
通过中转服务(Transit Server)查询远程 Oracle 数据库服务器的存储过程元数据,无需开放数据库端口。
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
AI Skill → HTTP → Transit Server (:6357) → WebSocket → Agent → Oracle
|
||||
```
|
||||
|
||||
## 前置条件
|
||||
|
||||
1. 中转服务已部署并运行(IP: 47.97.171.89, Port: 6357)
|
||||
2. Agent 已部署到数据库服务器并连接中转服务
|
||||
3. 本地已安装 Python 依赖:`pip install requests`
|
||||
|
||||
## 配置
|
||||
|
||||
配置文件位于技能目录下:`D:\work\恒诺\长期支持\跳板查询\demo\ai-skill\config.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"transit_url": "http://47.97.171.89:6357",
|
||||
"server_id": "server-001",
|
||||
"access_token": "",
|
||||
"expires_at": ""
|
||||
}
|
||||
```
|
||||
|
||||
使用查询命令前先登录中转机:
|
||||
|
||||
```bash
|
||||
python oracle_skill.py login <secretKey> [clientCode]
|
||||
```
|
||||
|
||||
登录成功后只保存中转机签发的 `access_token` 和过期时间,不保存 BOS `secretKey`。`clientCode` 是客户服务器编号,非必填;不传时中转机会默认选择 BOS 返回的第一个可用 client。
|
||||
|
||||
同一个 `secretKey` 同时只允许一个设备在线。另一台设备重新登录后,当前设备的 token 会立即失效,需要重新执行 `login <secretKey> [clientCode]`。
|
||||
|
||||
## 调用方式
|
||||
|
||||
使用 `scripts/oracle_skill.py` 脚本:
|
||||
|
||||
```bash
|
||||
python scripts/oracle_skill.py <command> [args]
|
||||
```
|
||||
|
||||
### 可用命令
|
||||
|
||||
| 命令 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| `analyze <schema> <proc>` | 完整分析存储过程 | `python oracle_skill.py analyze BOS M_RETAIL_SUBMIT` |
|
||||
| `list <schema>` | 列出 schema 下所有存储过程 | `python oracle_skill.py list BOS` |
|
||||
| `source <schema> <proc>` | 获取存储过程源码 | `python oracle_skill.py source BOS M_RETAIL_SUBMIT` |
|
||||
| `deps <schema> <proc>` | 获取依赖(表/存储过程) | `python oracle_skill.py deps BOS M_RETAIL_SUBMIT` |
|
||||
| `tables <schema> <proc>` | 获取相关表结构 | `python oracle_skill.py tables BOS M_RETAIL_SUBMIT` |
|
||||
| `describe <schema> <table>` | 查询表结构(列、索引、行数) | `python oracle_skill.py describe bosnds3 xcx_so` |
|
||||
| `discover [schema] [domain]` | 发现核心业务域(NL2SQL前置) | `python oracle_skill.py discover BOSNDS3 RETAIL` |
|
||||
| `nl2sql [schema] [domain]` | 生成 NL2SQL Schema 字典 | `python oracle_skill.py nl2sql BOSNDS3 RETAIL` |
|
||||
| `query <SQL>` | 执行 SELECT 查询,生产表必须带过滤条件和行数限制 | `python oracle_skill.py query "SELECT * FROM M_RETAIL WHERE BILLDATE=20260501 AND ROWNUM<=20"` |
|
||||
| `perm <userId> <tableId> [col]` | 查询用户数据权限 | `python oracle_skill.py perm 940 12983` |
|
||||
| `qperm <userId> <tableId> <SQL>` | 带权限过滤的查询 | `python oracle_skill.py qperm 940 12983 "SELECT * FROM M_OTHER_INOUT"` |
|
||||
| `login <secretKey> [clientCode]` | 登录中转机 + 选择客户服务器,clientCode 非必填 | `python oracle_skill.py login mykey HENLO` |
|
||||
| `logout` | 登出中转机并清除本地 token | `python oracle_skill.py logout` |
|
||||
| `status` | 查看中转机登录状态 + 当前 client | `python oracle_skill.py status` |
|
||||
| `switch <clientCode>` | 切换 client | `python oracle_skill.py switch OTHER_CLIENT` |
|
||||
| `clients` | 获取当前用户可访问 client 及在线状态 | `python oracle_skill.py clients` |
|
||||
| `servers` | 列出在线 Agent | `python oracle_skill.py servers` |
|
||||
| `health` | 检查中转服务状态 | `python oracle_skill.py health` |
|
||||
| `tablespace / tablespaces` | 查询表空间使用情况 | `python oracle_skill.py tablespace` |
|
||||
|
||||
### 交互模式
|
||||
|
||||
不传参数直接运行,进入交互模式:
|
||||
|
||||
```bash
|
||||
python scripts/oracle_skill.py
|
||||
```
|
||||
|
||||
## 生产查询限制
|
||||
|
||||
直接查询业务表时,必须带明确过滤条件,不要直接查询整表。生产环境数据量很大,`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
|
||||
```
|
||||
|
||||
## 常用业务对象说明
|
||||
|
||||
当用户使用商品、款号、条码、SKU、库存等业务词时,默认按以下对象理解:
|
||||
|
||||
- “商品”“款号”通常指 `M_PRODUCT` 表。
|
||||
- “条码”“SKU”通常指 `M_PRODUCT_ALIAS` 表。
|
||||
- 查询条码/SKU 时,首查 `M_PRODUCT_ALIAS.NO` 字段。
|
||||
- 款号和条码是一对多关系:一个 `M_PRODUCT` 可以对应多条 `M_PRODUCT_ALIAS`。
|
||||
- 如果涉及库存查询,通常查询 `V_FA_STORAGE` 视图。
|
||||
- `V_FA_STORAGE` 数据量很大,必须同时带店仓条件和款号/条码条件,不允许只查整张库存视图。
|
||||
|
||||
库存查询过滤规则:
|
||||
|
||||
- 店仓条件应优先使用门店、仓库、店仓 ID 或店仓编码等字段,先通过 `describe` 或 `AD_COLUMN` 确认实际字段名。
|
||||
- 款号条件走 `M_PRODUCT`;条码/SKU 条件走 `M_PRODUCT_ALIAS`。
|
||||
- 通过条码查库存时,应先用 `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
|
||||
```
|
||||
|
||||
## 分析报告内容
|
||||
|
||||
`analyze` 命令返回完整分析报告,包含:
|
||||
- **源码**:完整 PL/SQL 代码
|
||||
- **依赖**:涉及的表、视图、嵌套存储过程/函数
|
||||
- **表结构**:相关表的列信息(列名、类型、长度、可空)
|
||||
- **触发器**:相关表上的触发器列表
|
||||
|
||||
## 直接 HTTP 调用
|
||||
|
||||
不通过脚本,直接调用中转服务 API:
|
||||
|
||||
### 分析存储过程
|
||||
|
||||
```bash
|
||||
curl -X POST http://47.97.171.89:6357/api/query \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"server_id": "server-001",
|
||||
"action": "analyze_procedure",
|
||||
"schema": "BOS",
|
||||
"name": "M_RETAIL_SUBMIT",
|
||||
"timeout": 60
|
||||
}'
|
||||
```
|
||||
|
||||
### 查询表结构
|
||||
|
||||
```bash
|
||||
curl -X POST http://47.97.171.89:6357/api/query \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"server_id": "server-001",
|
||||
"action": "describe_table",
|
||||
"schema": "bosnds3",
|
||||
"name": "xcx_so",
|
||||
"timeout": 30
|
||||
}'
|
||||
```
|
||||
|
||||
### action 类型
|
||||
|
||||
| action | 说明 |
|
||||
|--------|------|
|
||||
| `analyze_procedure` | 完整分析 |
|
||||
| `list_procedures` | 列出存储过程 |
|
||||
| `get_source` | 源码 |
|
||||
| `get_dependencies` | 依赖 |
|
||||
| `get_tables` | 表结构(通过存储过程依赖) |
|
||||
| `describe_table` | 查询表结构(列、索引、行数、注释) |
|
||||
| `execute_query` | 执行 SELECT 查询(只读)—— 表空间查询也复用此 action |
|
||||
| `schema_discovery` | 发现核心业务域 |
|
||||
| `generate_nl2sql_schema` | 生成 NL2SQL Schema 字典 |
|
||||
|
||||
## 数据字典(AD_TABLE / AD_COLUMN / AD_REFBYTABLE)
|
||||
|
||||
### 通用查询规则
|
||||
|
||||
处理 BOS 业务单据(如零售单、采购单、调拨单、销售单等)时,必须遵循以下查询路径:
|
||||
|
||||
**1. 术语 → 表名(AD_TABLE)**
|
||||
|
||||
遇到不懂的业务术语(如"零售单提交"、"采购入库"),先查 AD_TABLE:
|
||||
|
||||
```sql
|
||||
SELECT ID, NAME, TABLENAME, DESCRIPTION, PROC_SUBMIT
|
||||
FROM AD_TABLE
|
||||
WHERE NAME LIKE '%关键词%' OR DESCRIPTION LIKE '%关键词%'
|
||||
```
|
||||
|
||||
- `NAME`:表名(英文,如 M_RETAIL)
|
||||
- `DESCRIPTION`:业务说明(中文,如"零售单")
|
||||
- `PROC_SUBMIT`:该单据的提交存储过程名称(非空即代表该表有提交逻辑)
|
||||
|
||||
**2. 字段含义(AD_COLUMN)**
|
||||
|
||||
不理解某个字段的业务含义时,查 AD_COLUMN:
|
||||
|
||||
```sql
|
||||
SELECT DBNAME, NAME, DESCRIPTION, COLTYPE
|
||||
FROM AD_COLUMN
|
||||
WHERE AD_TABLE_ID = <AD_TABLE.ID>
|
||||
ORDER BY ORDERNO
|
||||
```
|
||||
|
||||
**3. 主表 → 明细表(AD_REFBYTABLE)**
|
||||
|
||||
对于单据类表,其明细表、付款表等子表必须通过 AD_REFBYTABLE 查找,不要靠猜测命名规则:
|
||||
|
||||
```sql
|
||||
SELECT t1.NAME AS MAIN_TABLE,
|
||||
t2.NAME AS DETAIL_TABLE,
|
||||
c.DBNAME AS REF_COLUMN,
|
||||
r.ASSOCTYPE
|
||||
FROM AD_REFBYTABLE r
|
||||
LEFT JOIN AD_TABLE t1 ON r.AD_TABLE_ID = t1.ID
|
||||
LEFT JOIN AD_TABLE t2 ON r.AD_REFBY_TABLE_ID = t2.ID
|
||||
LEFT JOIN AD_COLUMN c ON r.AD_REFBY_COLUMN_ID = c.ID
|
||||
WHERE t1.NAME = '<AD_TABLE.NAME>'
|
||||
```
|
||||
|
||||
- `ASSOCTYPE`:"n"=一对多明细,"1"=强关联/嵌入
|
||||
- 得到明细表名后,再通过 AD_COLUMN 查看各明细表的字段含义
|
||||
|
||||
### 核心表说明
|
||||
|
||||
| 表 | 说明 |
|
||||
|------|------|
|
||||
| `AD_TABLE` | 所有业务表的元数据注册表,每条记录对应一张业务表 |
|
||||
| `AD_COLUMN` | 所有业务字段的元数据注册表,含字段名(DBNAME)、显示名(NAME)、描述(DESCRIPTION)、类型(COLTYPE)等 |
|
||||
| `AD_REFBYTABLE` | **主表与明细表的关联关系**,记录主表→明细表的外键引用 |
|
||||
|
||||
### AD_REFBYTABLE 关联字段
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `AD_TABLE_ID` | 主表ID → 关联 AD_TABLE.ID |
|
||||
| `AD_REFBY_TABLE_ID` | 明细表ID → 关联 AD_TABLE.ID |
|
||||
| `AD_REFBY_COLUMN_ID` | 明细表中的外键列ID → 关联 AD_COLUMN.ID,通过 AD_COLUMN.DBNAME 获取实际列名 |
|
||||
| `ASSOCTYPE` | 关联类型("1"=强关联/嵌入, "n"=一对多明细) |
|
||||
|
||||
### 查询主表→明细表关系的 SQL 模板
|
||||
|
||||
```sql
|
||||
SELECT t1.NAME AS MAIN_TABLE,
|
||||
t2.NAME AS DETAIL_TABLE,
|
||||
c.DBNAME AS REF_COLUMN,
|
||||
r.ASSOCTYPE
|
||||
FROM AD_REFBYTABLE r
|
||||
LEFT JOIN AD_TABLE t1 ON r.AD_TABLE_ID = t1.ID
|
||||
LEFT JOIN AD_TABLE t2 ON r.AD_REFBY_TABLE_ID = t2.ID
|
||||
LEFT JOIN AD_COLUMN c ON r.AD_REFBY_COLUMN_ID = c.ID
|
||||
WHERE t1.NAME = 'M_RETAIL'
|
||||
```
|
||||
|
||||
### 示例:M_RETAIL 的明细表
|
||||
|
||||
| 主表 | 明细表 | 外键列 | 关联类型 |
|
||||
|------|--------|--------|----------|
|
||||
| M_RETAIL | M_RETAILITEM | M_RETAIL_ID | n |
|
||||
| M_RETAIL | M_RETAILPAYITEM | M_RETAIL_ID | n |
|
||||
| M_RETAIL | M_RETAIL_PRO_ITEM | M_RETAIL_ID | n |
|
||||
| M_RETAIL | M_RETAIL_RATEITEM | M_RETAIL_ID | n |
|
||||
| M_RETAIL | M_RETAIL_DISITEM | M_RETAIL_ID | n |
|
||||
| M_RETAIL | M_RETAIL_VOUCHERSITEM | M_RETAIL_ID | n |
|
||||
| M_RETAIL | M_RETAIL_BATCHITEM | M_RETAIL_ID | n |
|
||||
|
||||
### 查询字段描述的 SQL 模板
|
||||
|
||||
```sql
|
||||
SELECT DBNAME, NAME, DESCRIPTION, COLTYPE
|
||||
FROM AD_COLUMN
|
||||
WHERE AD_TABLE_ID = (SELECT ID FROM AD_TABLE WHERE NAME = 'M_RETAILITEM')
|
||||
ORDER BY ORDERNO
|
||||
```
|
||||
|
||||
### BOS 系统地图分析(AD_TABLE_TEXT 经验)
|
||||
|
||||
`BOSNDS3.AD_TABLE_TEXT` 是 BOS 内部的表配置导出脚本生成器。分析该过程可以反推出 BOS 元数据体系:菜单、模块、业务表、字段、主子表、按钮动作、提交过程、权限目录和报表模板主要由数据字典表驱动。
|
||||
|
||||
当用户要求分析“BOS 系统菜单 / 模块目录 / 表结构地图 / 某个业务模块结构”时,优先按下面的元数据链路整理,不要只看物理表:
|
||||
|
||||
```text
|
||||
AD_SUBSYSTEM
|
||||
-> AD_TABLECATEGORY
|
||||
-> AD_ACCORDION
|
||||
-> AD_TABLE
|
||||
-> AD_COLUMN
|
||||
-> AD_REFBYTABLE
|
||||
-> AD_ACTION
|
||||
-> DIRECTORY
|
||||
-> AD_CXTAB / AD_CXTAB_JPARA / AD_CXTAB_DIMENSION / AD_CXTAB_FACT
|
||||
```
|
||||
|
||||
核心含义:
|
||||
|
||||
- `AD_SUBSYSTEM`:子系统。
|
||||
- `AD_TABLECATEGORY`:表类别 / 模块分类。
|
||||
- `AD_ACCORDION`:折叠菜单 / 菜单分组。
|
||||
- `AD_TABLE`:业务表注册表,含 `DESCRIPTION`、`PROC_SUBMIT`、`DIRECTORY_ID`、`AD_TABLECATEGORY_ID`、`AD_ACCORDION_ID` 等。
|
||||
- `AD_COLUMN`:字段元数据,含字段名、显示名、业务描述、控件类型、引用列、默认值、限定值组等。
|
||||
- `AD_REFBYTABLE`:主表到明细表、子表的关系。
|
||||
- `AD_ACTION`:表动作、按钮、URL、存储过程脚本入口。
|
||||
- `DIRECTORY`:数据权限目录挂载点。
|
||||
- `AD_CXTAB` 相关表:公开查询 / 报表模板及其参数、维度、指标。
|
||||
|
||||
常用系统地图 SQL:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
分析单个业务表时,至少同时检查:
|
||||
|
||||
- `AD_TABLE`:表归属、提交过程、权限目录。
|
||||
- `AD_COLUMN`:字段业务含义和值域。
|
||||
- `AD_REFBYTABLE`:明细表和外键列。
|
||||
- `AD_ACTION`:按钮和动作脚本。
|
||||
- `ALL_TRIGGERS` / `USER_OBJECTS`:触发器、同名前缀过程或函数。
|
||||
|
||||
注意:这套元数据能还原 BOS 业务结构,不等于完整物理数据库模型。复杂过程内部逻辑、动态 SQL、触发器副作用和前端特殊页面仍需要结合源码继续分析。
|
||||
|
||||
## 表空间查询
|
||||
|
||||
查询 Oracle 表空间使用情况。
|
||||
|
||||
### 自动降级策略
|
||||
|
||||
脚本按优先级尝试**5 种方式**,无需人工切换:
|
||||
|
||||
| 优先级 | 方式 | 数据来源 | 条件 | 输出字段 |
|
||||
|:---:|------|----------|------|----------|
|
||||
| 1️⃣ | 直接 DBA 查询 | `DBA_DATA_FILES` + `DBA_FREE_SPACE` | 用户有 `SELECT_CATALOG_ROLE` | 全部 8 个字段 |
|
||||
| 2️⃣ | DBA 专用函数 | `sys.get_tablespace_usage()`(返回 SYS_REFCURSOR) | DBA 已执行 CREATE FUNCTION + GRANT | 全部 5 个字段(自动解析) |
|
||||
| 3️⃣ | DBA 授权 VIEW(无前缀) | `HENLO_TS_USAGE` 视图 | DBA 已执行授权 SQL | 全部 8 个字段 |
|
||||
| 4️⃣ | DBA 授权 VIEW(sys.前缀) | `SYS.HENLO_TS_USAGE` 视图 | DBA 以 SYS 身份创建时自动处理 | 全部 8 个字段 |
|
||||
| 5️⃣ | 用户视图 | `USER_FREE_SPACE` | 始终可用 | 仅表空间名称 + 剩余MB |
|
||||
|
||||
> **经验**:DBA 以 SYS 身份登录创建的 VIEW 会归属到 `SYS` schema,需用 `sys.HENLO_TS_USAGE` 查询。脚本会自动先试无前缀、再试 `sys.` 前缀。
|
||||
|
||||
### 给 DBA 的授权 SQL
|
||||
|
||||
如果当前用户缺少系统视图权限,脚本会**自动输出**以下 SQL。将其交给 DBA 在 Oracle 中执行一次:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE VIEW SYS.HENLO_TS_USAGE AS
|
||||
SELECT
|
||||
df.tablespace_name AS "表空间名称",
|
||||
ROUND(df.total_bytes / 1048576, 1) AS "总大小MB",
|
||||
ROUND((df.total_bytes - NVL(fs.free_bytes, 0)) / 1048576, 1) AS "已用MB",
|
||||
ROUND(NVL(fs.free_bytes, 0) / 1048576, 1) AS "剩余MB",
|
||||
ROUND((df.total_bytes - NVL(fs.free_bytes, 0)) / df.total_bytes * 100, 1) AS "使用率%",
|
||||
df.autoextensible AS "自动拓展",
|
||||
ROUND(df.max_bytes / 1048576, 1) AS "最大可拓展MB",
|
||||
ROUND((df.total_bytes - NVL(fs.free_bytes, 0)) / NULLIF(df.max_bytes, 0) * 100, 1) AS "最大使用率%"
|
||||
FROM (
|
||||
SELECT
|
||||
tablespace_name,
|
||||
SUM(bytes) AS total_bytes,
|
||||
SUM(CASE WHEN autoextensible = 'YES' THEN maxbytes ELSE bytes END) AS max_bytes,
|
||||
MAX(CASE WHEN autoextensible = 'YES' THEN 'YES' ELSE 'NO' END) AS autoextensible
|
||||
FROM dba_data_files
|
||||
GROUP BY tablespace_name
|
||||
) df
|
||||
LEFT JOIN (
|
||||
SELECT tablespace_name, SUM(bytes) AS free_bytes
|
||||
FROM dba_free_space
|
||||
GROUP BY tablespace_name
|
||||
) fs ON df.tablespace_name = fs.tablespace_name
|
||||
ORDER BY 6 DESC;
|
||||
|
||||
GRANT SELECT ON SYS.HENLO_TS_USAGE TO bosnds3;
|
||||
```
|
||||
|
||||
> **原理**:Oracle 视图默认使用**定义者权限**(`DEFINER`),以视图创建者的 DBA 身份执行,普通用户仅需视图的 `SELECT` 权限。这比授予 `SELECT_CATALOG_ROLE` 更安全——只暴露这一个视图的数据。
|
||||
|
||||
DBA 执行授权后,再次运行 `tablespace` 命令即可自动使用完整查询。
|
||||
|
||||
### 输出字段
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| 表空间名称 | 表空间名称 |
|
||||
| 总大小MB | 当前所有数据文件总大小 |
|
||||
| 已用MB | 已使用的空间 |
|
||||
| 剩余MB | 剩余可用空间 |
|
||||
| 使用率% | 已用 / 总大小 × 100% |
|
||||
| 自动拓展 | YES=自动扩展,NO=不自动扩展 |
|
||||
| 最大可拓展MB | 开启自动扩展后的最大可达大小 |
|
||||
| 最大使用率% | 已用 / 最大可拓展 × 100%(参考阈值 5%) |
|
||||
|
||||
### 触发语法
|
||||
|
||||
用户可以说:
|
||||
- 「帮我查询下表空间」
|
||||
- 「查看表空间使用情况」
|
||||
- 「表空间是否够用」
|
||||
|
||||
```bash
|
||||
python oracle_skill.py tablespace
|
||||
# 或
|
||||
python oracle_skill.py tablespaces
|
||||
```
|
||||
|
||||
### 阈值规则
|
||||
|
||||
| 使用率 | 状态 | 建议 |
|
||||
|--------|------|------|
|
||||
| < 80% | ✅ 正常 | 无需处理 |
|
||||
| 80~95% | 🔶 关注 | 评估未来增长,制定扩容计划 |
|
||||
| ≥ 95% | ⚠️ 紧急 | 尽快扩容或清理空间! |
|
||||
|
||||
> **智能告警规则**:脚本逐行解析表空间数据,自动判断衡量指标。
|
||||
> 若表空间**已开启自动扩展**(`自动拓展=YES`),按 **最大使用率%** 判断(已用/最大可拓展);
|
||||
> 若**未开启**(`NO`),按当前 **使用率%** 判断(已用/当前总大小)。
|
||||
>
|
||||
> 这让告警更准确。例如:SYSTEM 使用率 99.4% 但最大使用率仅 3.7%,说明只是当前数据文件写满了,自动扩展后即释放空间,并非真正的存储瓶颈。
|
||||
|
||||
### 使用场景
|
||||
|
||||
1. **查主表的明细表**:通过 AD_REFBYTABLE 找到主表关联的所有明细表及外键列
|
||||
2. **查字段含义**:通过 AD_COLUMN 的 DESCRIPTION 字段了解业务含义
|
||||
3. **构建 JOIN 查询**:根据外键列名自动拼接主表→明细表的 JOIN 条件
|
||||
4. **理解业务模型**:通过表间关系理解业务单据结构(如零售单→零售明细→支付明细)
|
||||
|
||||
### 4. 统计数据场景的过滤条件
|
||||
|
||||
在 BOS 系统中,进行统计数据查询时,必须遵循以下业务规则:
|
||||
|
||||
**业务单据通用过滤条件**:
|
||||
- `ISACTIVE = 'Y'`:单据有效(Y=可用,N=已删除/作废)
|
||||
- `STATUS = '2'`:单据已提交(1=未提交,2=已提交,3=审批中)
|
||||
|
||||
**查询模板**:
|
||||
```sql
|
||||
-- 查询有效且已提交的业务单据
|
||||
SELECT * FROM <业务表名>
|
||||
WHERE ISACTIVE = 'Y' AND STATUS = '2'
|
||||
-- 其他业务条件...
|
||||
```
|
||||
|
||||
**字段含义**:
|
||||
| 字段 | 值 | 业务含义 |
|
||||
|------|-----|----------|
|
||||
| `ISACTIVE` | 'Y' | 单据有效,可参与统计 |
|
||||
| `ISACTIVE` | 'N' | 单据已删除/作废,应排除 |
|
||||
| `STATUS` | '1' | 草稿/未提交,应排除 |
|
||||
| `STATUS` | '2' | **已提交**,可参与统计 |
|
||||
| `STATUS` | '3' | 审批中,通常排除(除非统计审批流程) |
|
||||
|
||||
**应用场景**:
|
||||
- 统计销售额、销售量 → 必须用 `ISACTIVE='Y' AND STATUS='2'`
|
||||
- 查询历史订单 → 必须用 `ISACTIVE='Y' AND STATUS='2'`
|
||||
- 分析业务趋势 → 必须用 `ISACTIVE='Y' AND STATUS='2'`
|
||||
|
||||
**注意事项**:
|
||||
1. 明细表(如 M_RETAILITEM)通常继承主表状态,但有时也有自己的状态字段
|
||||
2. 部分表可能使用 `ISSTOP` 代替 `ISACTIVE`,逻辑相反('Y'=停用)
|
||||
3. 查询前应先通过 AD_COLUMN 确认字段名和值域
|
||||
|
||||
## 数据权限系统
|
||||
|
||||
### GET_USERSPERMSQL 函数
|
||||
|
||||
数据库内置 `get_userspermsql` 函数,用于获取用户的数据权限过滤条件。
|
||||
|
||||
**函数签名:**
|
||||
```sql
|
||||
FUNCTION get_userspermsql(
|
||||
p_users_id NUMBER, -- 用户ID (USERS.ID)
|
||||
p_tableid NUMBER, -- 表ID (AD_TABLE.ID)
|
||||
p_col VARCHAR2 -- 字段名 (AD_COLUMN.DBNAME),可为NULL
|
||||
) RETURN CLOB -- 返回权限过滤SQL
|
||||
```
|
||||
|
||||
**返回值:**
|
||||
- 空字符串:全权限(无需过滤)
|
||||
- SQL条件:如 `C_STORE_ID IN (...)`,需拼接到 WHERE 子句
|
||||
|
||||
**权限模型:**
|
||||
```
|
||||
用户 → GROUPUSER → 用户组 → GROUPPERM → 安全目录 → 权限SQL
|
||||
↓
|
||||
AD_TABLE.DIRECTORY_ID
|
||||
```
|
||||
|
||||
### 使用权限过滤查询
|
||||
|
||||
**1. 查询用户权限:**
|
||||
```bash
|
||||
python oracle_skill.py perm 940 12983
|
||||
```
|
||||
返回:
|
||||
```json
|
||||
{
|
||||
"user_id": "940",
|
||||
"table_id": "12983",
|
||||
"perm_sql": "M_OTHER_INOUT.C_STORE_ID IN(...)",
|
||||
"has_restriction": true
|
||||
}
|
||||
```
|
||||
|
||||
**2. 带权限过滤的查询:**
|
||||
```bash
|
||||
python oracle_skill.py qperm 940 12983 "SELECT * FROM M_OTHER_INOUT WHERE BILLDATE=20260501"
|
||||
```
|
||||
自动拼接权限条件后执行:
|
||||
```sql
|
||||
SELECT * FROM M_OTHER_INOUT
|
||||
WHERE BILLDATE=20260501
|
||||
AND M_OTHER_INOUT.C_STORE_ID IN(...)
|
||||
```
|
||||
|
||||
### 常用表ID参考
|
||||
|
||||
| 表名 | AD_TABLE.ID | 说明 |
|
||||
|------|-------------|------|
|
||||
| M_RETAIL | 12964 | 零售单主表 |
|
||||
| M_RETAILITEM | 12965 | 零售明细 |
|
||||
| M_OTHER_INOUT | 12983 | 其他出入库 |
|
||||
| C_STORE_CHKDAY | 18182 | 门店盘点日 |
|
||||
|
||||
## 故障排查
|
||||
|
||||
| 问题 | 排查 |
|
||||
|------|------|
|
||||
| `无法连接中转服务` | 检查 transit_url 地址和端口 |
|
||||
| `agent not found` | 确认 Agent 已启动并连接成功 |
|
||||
| `请求超时` | Agent 可能卡住,增大 timeout 参数 |
|
||||
| Oracle 连接失败 | 检查 Agent 的 config.json 中 Oracle 配置 |
|
||||
|
||||
## Oracle 日常运维监控触发
|
||||
|
||||
当用户说“给我 HENLO 的 Oracle 运维报告”、“生成 HENLO 数据库日报”、“做一次 HENLO Oracle 巡检”这类请求时,调用:
|
||||
|
||||
```bash
|
||||
python scripts/oracle_skill.py ops_report HENLO
|
||||
```
|
||||
|
||||
当用户询问单项运维状态时,调用 `ops <item> [clientCode]`:
|
||||
|
||||
```bash
|
||||
python scripts/oracle_skill.py ops blocking_locks HENLO
|
||||
python scripts/oracle_skill.py ops active_slow_sql HENLO
|
||||
python scripts/oracle_skill.py ops ora_errors HENLO
|
||||
```
|
||||
|
||||
常用自然语言映射:
|
||||
|
||||
| 用户意图 | 命令 |
|
||||
|---|---|
|
||||
| 有没有锁阻塞 | `ops blocking_locks <clientCode>` |
|
||||
| 当前有没有慢 SQL | `ops active_slow_sql <clientCode>` |
|
||||
| 最近 ORA 错误 | `ops ora_errors <clientCode>` |
|
||||
| UNDO 风险 | `ops undo <clientCode>` |
|
||||
| IO 等待 | `ops io_waits <clientCode>` |
|
||||
| 内存使用 | `ops memory <clientCode>` |
|
||||
| 失效对象 | `ops invalid_objects <clientCode>` |
|
||||
|
||||
涉及 SYS/DBA 权限视图时,Agent 会优先调用 `SYS.HENLO_ORA_MONITOR`;如果不可用,再尝试当前登录账号下的 `HENLO_ORA_MONITOR`。如果两个函数都不存在或未授权,输出两种安装方案:有 SYS 账号时安装到 SYS 并授权;没有 SYS 账号但当前登录账号已有系统视图查询权限时,安装到当前账号后重试。
|
||||
|
||||
## 服务器体检报告触发
|
||||
|
||||
当用户说“给我 HENLO 的服务器体检报告”、“查询 HENLO 的服务器状态”、“看看 HENLO 的备份情况”这类请求时,调用:
|
||||
|
||||
```bash
|
||||
python scripts/oracle_skill.py checkup HENLO
|
||||
```
|
||||
|
||||
如果用户没有指定客户服务器编号,则调用:
|
||||
|
||||
```bash
|
||||
python scripts/oracle_skill.py checkup
|
||||
```
|
||||
|
||||
输出字段固定为 `clientCode`、`info_cpu_rate`、`info_memory_rate`、`info_memory`、`bak_path`、`bak_lastdate`、`computer`。`clientCode` 是客户服务器编号,非必填;不传时使用当前登录 client。
|
||||
|
||||
## 新增业务记录 SQL 生成规则
|
||||
|
||||
当用户要求分析或生成新增业务表记录的 SQL 示例时,仍然保持只读安全边界:skill 可以生成 SQL 和说明,但不能直接通过查询通道执行 INSERT、UPDATE、DELETE、MERGE、DDL 等写操作。
|
||||
|
||||
生成新增记录 SQL 时遵守以下默认规则:
|
||||
|
||||
- 主表或子表新增记录的主键 `ID` 使用 `get_sequences('<表名称>')` 取值。
|
||||
- 如果目标表存在 `DOCNO` 字段,先查询 `AD_COLUMN` 中该字段是否配置 `SEQUENCENAME` 单据编号生成器。
|
||||
- 如果 `DOCNO` 对应的 `SEQUENCENAME` 有值,则单据编号使用 `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'` 表示草稿/未提交;提交人、提交时间等字段由提交动作或提交存储过程处理。
|
||||
- 如果用户明确提到“提交”,通常不是直接把 `STATUS` 改成 `'2'`,而是应先查询 `AD_TABLE.PROC_SUBMIT`,按该表配置的提交存储过程理解提交逻辑。
|
||||
|
||||
查询 `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 = <AD_LIMITVALUE_GROUP_ID>
|
||||
ORDER BY ORDERNO, ID
|
||||
```
|
||||
Reference in New Issue
Block a user