制造业质量追溯02:用 Oracle 26ai 属性图(Property Graph)搞定工业网状追溯
2026-09-24 07:20 AlfredZhao 阅读(40) 评论(0) 收藏 举报本文继续探讨轮胎制造场景(已简化,实际会更复杂),一旦某台设备报警,最头疼的问题往往是:这台设备生产的半成品,最终流到了哪些成品轮胎上?又是谁组装的?传统做法靠多表自联接加 CONNECT BY 递归硬凑,SQL 又长又难维护。此时若在合适的场景下使用 Oracle 属性图,查询思路往往会更清晰。
01 | 先建三张基础表
追溯的骨架是设备、人员、生产履历三张表。设备表记录密炼机、胎面挤出机、成型机等,状态含 NORMAL 与 ALARM;人员表记录操作工与所属班组;生产履历表则把「哪个批次、由哪台设备、在哪个工人操作下生产」这条关系固定下来。
-- 前置:lot_master 与 lot_genealogy 沿用第 01 篇定义,此处不再重复
-- 若单独运行本文脚本,请先创建这两张表并插入对应批次数据
CREATE TABLE equipment_master (
eq_id VARCHAR2(50) PRIMARY KEY,
eq_name VARCHAR2(100) NOT NULL,
eq_type VARCHAR2(30) NOT NULL,
status VARCHAR2(20) DEFAULT 'NORMAL'
);
CREATE TABLE operator_master (
op_id VARCHAR2(50) PRIMARY KEY,
op_name VARCHAR2(100) NOT NULL,
shift_group VARCHAR2(20) NOT NULL
);
CREATE TABLE production_history (
lot_id VARCHAR2(50) NOT NULL,
eq_id VARCHAR2(50) NOT NULL,
op_id VARCHAR2(50) NOT NULL,
produce_time DATE DEFAULT SYSDATE,
CONSTRAINT pk_prod_hist PRIMARY KEY (lot_id, eq_id, op_id),
CONSTRAINT fk_ph_lot FOREIGN KEY (lot_id) REFERENCES lot_master(lot_id),
CONSTRAINT fk_ph_eq FOREIGN KEY (eq_id) REFERENCES equipment_master(eq_id),
CONSTRAINT fk_ph_op FOREIGN KEY (op_id) REFERENCES operator_master(op_id)
);
--插入测试数据
BEGIN
-- 插入设备数据(密炼机 EQ-MIXER-01 状态设为 ALARM 报警)
INSERT INTO equipment_master VALUES ('EQ-MIXER-01', '1号密炼机', 'MIXER', 'ALARM');
INSERT INTO equipment_master VALUES ('EQ-BUILD-02', '2号轮胎成型机', 'BUILDING_MACHINE', 'NORMAL');
-- 插入人员数据
INSERT INTO operator_master VALUES ('OP-ZHANG-01', '张工(密炼主操)', 'A_SHIFT');
INSERT INTO operator_master VALUES ('OP-LI-02', '李工(成型主操)', 'B_SHIFT');
-- 插入生产履历关系
-- 混炼胶 SEMI-COMPOUND-101 是在 故障密炼机 EQ-MIXER-01 上由 张工 生产的
INSERT INTO production_history VALUES ('SEMI-COMPOUND-101', 'EQ-MIXER-01', 'OP-ZHANG-01', DATE '2026-01-02');
-- 成品轮胎 FG-TIRE-DOT-8888 是在 2号成型机 上由 李工 组装的
INSERT INTO production_history VALUES ('FG-TIRE-DOT-8888', 'EQ-BUILD-02', 'OP-LI-02', DATE '2026-01-05');
COMMIT;
END;
/
测试数据里,EQ-MIXER-01 被设为 ALARM,它生产的半成品 SEMI-COMPOUND-101 由张工操作;成品轮胎 FG-TIRE-DOT-8888 则在 EQ-BUILD-02 上由李工组装。
这三张表之间的引用关系,可以用一张图先理清楚——设备、人员、批次各自是节点,生产履历把批次分别连到设备和人员上:
02 | 把关系表声明成属性图
属性图的价值在于:把「点」和「边」显式声明出来,查询时就能用图模式匹配,而不是反复自联接。
CREATE PROPERTY GRAPH industrial_trace_graph
VERTEX TABLES (
lot_master KEY (lot_id) LABEL LOT
PROPERTIES (lot_id, item_name, item_type),
equipment_master KEY (eq_id) LABEL EQUIPMENT
PROPERTIES (eq_id, eq_name, eq_type, status),
operator_master KEY (op_id) LABEL OPERATOR
PROPERTIES (op_id, op_name, shift_group)
)
EDGE TABLES (
lot_genealogy
KEY (parent_lot_id, child_lot_id)
SOURCE KEY (parent_lot_id) REFERENCES lot_master(lot_id)
DESTINATION KEY (child_lot_id) REFERENCES lot_master(lot_id)
LABEL CONSUMES
PROPERTIES (quantity_used),
production_history AS lot_produced_on_eq
KEY (lot_id, eq_id)
SOURCE KEY (lot_id) REFERENCES lot_master(lot_id)
DESTINATION KEY (eq_id) REFERENCES equipment_master(eq_id)
LABEL PRODUCED_ON,
production_history AS lot_operated_by_op
KEY (lot_id, op_id)
SOURCE KEY (lot_id) REFERENCES lot_master(lot_id)
DESTINATION KEY (op_id) REFERENCES operator_master(op_id)
LABEL OPERATED_BY
);
这里定义了三种边:批次消耗批次(CONSUMES)、批次生产于设备(PRODUCED_ON)、批次由人员操作(OPERATED_BY)。
需要留意的是,production_history 这张表被复用了两次,分别声明成 lot_produced_on_eq 和 lot_operated_by_op 两条边。也就是说,同一张关系表可以按不同的语义拆成多条边,这正是属性图把「关系」显式化的体现——表还是那张表,但图里它承担了两种角色。
03 | 三种查询写法对比
传统 CONNECT BY 写法要先用子查询找故障设备的初始批次,再沿物料树递归,最后外联生产履历找组装工人,多层嵌套,可读性差。
-- 1.传统 CONNECT BY 写法:多层子查询与自联接硬凑
SELECT
eq.eq_name AS alarm_equipment,
t.trace_path,
t.final_lot_id,
m_final.item_name AS final_item_name,
op.op_name AS final_assembly_operator
FROM (
-- 第一步:找故障设备生产的初始批次
SELECT ph.lot_id AS start_lot_id, ph.eq_id
FROM production_history ph
JOIN equipment_master eq ON ph.eq_id = eq.eq_id
WHERE eq.status = 'ALARM'
) eq_start
-- 第二步:用 CONNECT BY 沿着物料树向下递归
JOIN (
SELECT
CONNECT_BY_ROOT parent_lot_id AS root_lot,
SYS_CONNECT_BY_PATH(parent_lot_id, ' -> ') || ' -> ' || child_lot_id AS trace_path,
child_lot_id AS final_lot_id
FROM lot_genealogy
CONNECT BY PRIOR child_lot_id = parent_lot_id
) t ON eq_start.start_lot_id = t.root_lot
JOIN equipment_master eq ON eq_start.eq_id = eq.eq_id
JOIN lot_master m_final ON t.final_lot_id = m_final.lot_id
-- 第三步:再外联生产履历查找终极成品的组装工人
LEFT JOIN production_history ph_final ON t.final_lot_id = ph_final.lot_id
LEFT JOIN operator_master op ON ph_final.op_id = op.op_id;
属性图的 GRAPH_TABLE 写法则是声明式的:先匹配报警设备生产的半成品,再沿 CONSUMES 变长递归 1~5 跳找到成品轮胎,最后匹配组装人员。
-- 2.属性图的写法
SELECT
gt.alarm_eq_name,
gt.affected_semi_lot,
gt.final_tire_lot,
gt.final_tire_name,
gt.assembly_op_name
FROM GRAPH_TABLE ( industrial_trace_graph
MATCH
-- 1. 匹配故障设备生产的半成品胶料
(eq IS EQUIPMENT WHERE eq.status = 'ALARM')<-[IS PRODUCED_ON]-(semi IS LOT)
-- 2. 从半成品胶料变长递归 1~5 跳找到最终成品轮胎
-[IS CONSUMES]->{1, 5} (tire IS LOT WHERE tire.item_type = 'FG' OR tire.item_type = 'CUST')
-- 3. 匹配成品轮胎的组装人员
-[IS OPERATED_BY]->(op IS OPERATOR)
COLUMNS (
eq.eq_name AS alarm_eq_name,
semi.lot_id AS affected_semi_lot,
tire.lot_id AS final_tire_lot,
tire.item_name AS final_tire_name,
op.op_name AS assembly_op_name
)
) gt;
如果只想让图引擎专注物料树遍历,人员关联放到外层做传统 LEFT JOIN 也可以,这就是混合模式,能保证记录不漏。
-- 3.属性图专注物料树遍历,人员关联放到外层的混合查询写法
SELECT
gt.alarm_eq_name,
gt.affected_semi_lot,
gt.target_lot_id,
gt.target_item_name,
gt.target_item_type,
op.op_name AS assembly_op_name -- 外层关联出来的工人名
FROM GRAPH_TABLE ( industrial_trace_graph
MATCH
-- 图引擎只专注于复杂的网状物料树遍历
(eq IS EQUIPMENT WHERE eq.status = 'ALARM')<-[IS PRODUCED_ON]-(semi IS LOT)
-[IS CONSUMES]->{1, 5} (target IS LOT)
COLUMNS (
eq.eq_name AS alarm_eq_name,
semi.lot_id AS affected_semi_lot,
target.lot_id AS target_lot_id,
target.item_name AS target_item_name,
target.item_type AS target_item_type
)
) gt
-- 扩展节点(工人)放到外层做传统 LEFT JOIN,绝不漏掉记录
LEFT JOIN production_history ph ON gt.target_lot_id = ph.lot_id
LEFT JOIN equipment_master eq_final ON ph.eq_id = eq_final.eq_id AND eq_final.eq_type = 'BUILDING_MACHINE'
LEFT JOIN operator_master op ON ph.op_id = op.op_id;
三种写法的差异,可以用一张流程图概括:传统写法把「找起点、递归、外联」拆成三段各自为战;属性图写法把整条追溯路径压进一个 MATCH 模式;混合模式则在图遍历之后,把非核心的关联交回关系型 LEFT JOIN。
04 | 小结
属性图把复杂的网状物料追溯变成了一句声明式匹配,递归跳数、节点条件都写在模式里,在本文这类关系密集、路径较深的场景下可读性更好。是否带来性能与维护收益,仍需结合所用 Oracle 版本、数据规模和实际执行计划评估。
关注我,和AI一起成长~
转载请注明原文链接:https://www.cnblogs.com/jyzhao/p/23104299
👋 感谢阅读,欢迎关注我的公众号 「赵靖宇」
浙公网安备 33010602011771号