26 KiB
name, description
| name | description |
|---|---|
| oracle-jump-query | Oracle 跳板查询技能。通过中转服务查询远程 Oracle 数据库的元数据(存储过程源码、依赖、表结构、触发器、直接查表),连接数据库为只读,禁止任何写操作。当用户需要分析 Oracle 存储过程、查找依赖表、查询表结构、查看业务逻辑时触发。 |
Oracle 跳板查询
版本:v1.5.8 · 更新日志
概述
通过中转服务(Transit Server)查询远程 Oracle 数据库服务器的存储过程元数据,无需开放数据库端口。
架构
AI Skill → HTTP → Transit Server (:6357) → WebSocket → Agent → Oracle
前置条件
- 中转服务已部署并运行(IP: 47.97.171.89, Port: 6357)
- Agent 已部署到数据库服务器并连接中转服务
- 本地已安装 Python 依赖:
pip install requests
配置
配置文件位于技能目录下:D:\work\恒诺\长期支持\跳板查询\demo\ai-skill\config.json
{
"transit_url": "http://47.97.171.89:6357",
"server_id": "server-001",
"access_token": "",
"expires_at": ""
}
使用查询命令前先登录中转机:
python oracle_skill.py login <secretKey> [clientCode]
登录成功后只保存中转机签发的 access_token 和过期时间,不保存 BOS secretKey。clientCode 是客户服务器编号,非必填;不传时中转机会默认选择 BOS 返回的第一个可用 client。
同一个 secretKey 同时只允许一个设备在线。另一台设备重新登录后,当前设备的 token 会立即失效,需要重新执行 login <secretKey> [clientCode]。
调用方式
使用 scripts/oracle_skill.py 脚本:
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 |
交互模式
不传参数直接运行,进入交互模式:
python scripts/oracle_skill.py
生产查询限制
直接查询业务表时,必须带明确过滤条件,不要直接查询整表。生产环境数据量很大,SELECT * FROM <table> 这类无条件查询可能返回大量数据、拖慢 Agent 或影响数据库。
生成或执行 query / qperm SQL 时遵守:
- 必须有
WHERE条件,优先使用日期、单号、门店、客户、状态、主键等业务过滤条件。 - 必须加行数限制,例如
ROWNUM <= 20;需要分页时分批查询。 - 不要为了“先看看数据”执行无条件整表查询。
- 统计查询也要限定业务范围,例如日期区间、单据状态、门店范围。
- 如果用户没有给出过滤条件,先追问条件,或先用
describe/AD_COLUMN/AD_TABLE查询结构和字段含义。
推荐示例:
SELECT *
FROM M_RETAIL
WHERE BILLDATE = 20260501
AND STATUS = '2'
AND ROWNUM <= 20
避免示例:
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或分页限制;如果用户没有提供店仓或款号/条码,先追问,不要直接查询库存视图。
示例思路:
-- 伪示例:实际字段名需先 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:
分析存储过程
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
}'
查询表结构
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:
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:
SELECT DBNAME, NAME, DESCRIPTION, COLTYPE
FROM AD_COLUMN
WHERE AD_TABLE_ID = <AD_TABLE.ID>
ORDER BY ORDERNO
3. 主表 → 明细表(AD_REFBYTABLE)
对于单据类表,其明细表、付款表等子表必须通过 AD_REFBYTABLE 查找,不要靠猜测命名规则:
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 模板
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 模板
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 系统菜单 / 模块目录 / 表结构地图 / 某个业务模块结构”时,优先按下面的元数据链路整理,不要只看物理表:
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:
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 会归属到
SYSschema,需用sys.HENLO_TS_USAGE查询。脚本会自动先试无前缀、再试sys.前缀。
给 DBA 的授权 SQL
如果当前用户缺少系统视图权限,脚本会自动输出以下 SQL。将其交给 DBA 在 Oracle 中执行一次:
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%) |
触发语法
用户可以说:
- 「帮我查询下表空间」
- 「查看表空间使用情况」
- 「表空间是否够用」
python oracle_skill.py tablespace
# 或
python oracle_skill.py tablespaces
阈值规则
| 使用率 | 状态 | 建议 |
|---|---|---|
| < 80% | ✅ 正常 | 无需处理 |
| 80~95% | 🔶 关注 | 评估未来增长,制定扩容计划 |
| ≥ 95% | ⚠️ 紧急 | 尽快扩容或清理空间! |
智能告警规则:脚本逐行解析表空间数据,自动判断衡量指标。 若表空间已开启自动扩展(
自动拓展=YES),按 最大使用率% 判断(已用/最大可拓展); 若未开启(NO),按当前 使用率% 判断(已用/当前总大小)。这让告警更准确。例如:SYSTEM 使用率 99.4% 但最大使用率仅 3.7%,说明只是当前数据文件写满了,自动扩展后即释放空间,并非真正的存储瓶颈。
使用场景
- 查主表的明细表:通过 AD_REFBYTABLE 找到主表关联的所有明细表及外键列
- 查字段含义:通过 AD_COLUMN 的 DESCRIPTION 字段了解业务含义
- 构建 JOIN 查询:根据外键列名自动拼接主表→明细表的 JOIN 条件
- 理解业务模型:通过表间关系理解业务单据结构(如零售单→零售明细→支付明细)
4. 统计数据场景的过滤条件
在 BOS 系统中,进行统计数据查询时,必须遵循以下业务规则:
业务单据通用过滤条件:
ISACTIVE = 'Y':单据有效(Y=可用,N=已删除/作废)STATUS = '2':单据已提交(1=未提交,2=已提交,3=审批中)
查询模板:
-- 查询有效且已提交的业务单据
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'
注意事项:
- 明细表(如 M_RETAILITEM)通常继承主表状态,但有时也有自己的状态字段
- 部分表可能使用
ISSTOP代替ISACTIVE,逻辑相反('Y'=停用) - 查询前应先通过 AD_COLUMN 确认字段名和值域
数据权限系统
GET_USERSPERMSQL 函数
数据库内置 get_userspermsql 函数,用于获取用户的数据权限过滤条件。
函数签名:
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. 查询用户权限:
python oracle_skill.py perm 940 12983
返回:
{
"user_id": "940",
"table_id": "12983",
"perm_sql": "M_OTHER_INOUT.C_STORE_ID IN(...)",
"has_restriction": true
}
2. 带权限过滤的查询:
python oracle_skill.py qperm 940 12983 "SELECT * FROM M_OTHER_INOUT WHERE BILLDATE=20260501"
自动拼接权限条件后执行:
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 巡检”这类请求时,调用:
python scripts/oracle_skill.py ops_report HENLO
当用户询问单项运维状态时,调用 ops <item> [clientCode]:
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 的备份情况”这类请求时,调用:
python scripts/oracle_skill.py checkup HENLO
如果用户没有指定客户服务器编号,则调用:
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 编号生成器示例:
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。因此用户说“类型为券核销”时,应生成:
XH_ORDER_FTP.BILLTYPE = 'VOU_USED'
查询字段值域映射模板:
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
使用时先查字段:
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 有值,再查:
SELECT VALUE, NAME AS DISPLAY_NAME
FROM AD_LIMITVALUE
WHERE AD_LIMITVALUE_GROUP_ID = <AD_LIMITVALUE_GROUP_ID>
ORDER BY ORDERNO, ID