上一篇
场景引入:
小明最近在用Oracle开发时遇到个头疼问题——他创建了一个基于多表的视图(View),想通过视图直接插入数据,结果系统报错:“ORA-01779: 无法修改与非键值保存表对应的列” 😫,这到底是怎么回事?难道多表视图就不能insert了吗?别急,今天我们就来拆解这个难题!
Oracle对视图的DML操作(insert/update/delete)有严格限制:
举个栗子🌰:
-- 表1(主键id) CREATE TABLE department ( dept_id NUMBER PRIMARY KEY, dept_name VARCHAR2(50) ); -- 表2(外键dept_id关联department) CREATE TABLE employee ( emp_id NUMBER PRIMARY KEY, emp_name VARCHAR2(50), dept_id NUMBER REFERENCES department(dept_id) ); -- 多表视图(违反键值保存规则) CREATE VIEW emp_dept_view AS SELECT e.emp_id, e.emp_name, d.dept_name FROM employee e, department d WHERE e.dept_id = d.dept_id;
这个视图如果直接执行INSERT INTO emp_dept_view VALUES(...)
会报错,因为:
department
表的主键dept_id
未出现在视图中 如果业务允许,只针对需要insert的表创建视图:
CREATE VIEW emp_view AS SELECT emp_id, emp_name, dept_id FROM employee; -- 此时可直接insert ✅
通过触发器手动指定insert逻辑:
CREATE OR REPLACE TRIGGER emp_dept_insert INSTEAD OF INSERT ON emp_dept_view FOR EACH ROW BEGIN -- 先插入部门(假设dept_name唯一) INSERT INTO department(dept_id, dept_name) VALUES (dept_seq.nextval, :NEW.dept_name); -- 再插入员工 INSERT INTO employee(emp_id, emp_name, dept_id) VALUES (emp_seq.nextval, :NEW.emp_name, dept_seq.currval); END;
优点:完全自定义操作逻辑 🎯
修改视图包含所有必要主键:
CREATE VIEW emp_dept_safe_view AS SELECT e.emp_id, e.emp_name, e.dept_id, d.dept_name FROM employee e, department d WHERE e.dept_id = d.dept_id; -- 此时可对employee表字段进行insert ✅
BEGIN -- 先插入主表 INSERT INTO department(dept_id, dept_name) VALUES (1, 'IT'); -- 再插入从表 INSERT INTO employee(emp_id, emp_name, dept_id) VALUES (1001, '张三', 1); COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; END;
小知识:Oracle 23c开始支持SQL标准中的WITH CHECK OPTION
增强,对视图DML有更细粒度控制~
本文由 依瑞 于2025-08-04发表在【云服务器提供商】,文中图片由(依瑞)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://up.7tqx.com/wenda/535639.html
发表评论