我正在尝试使用此更改表的主要内容,
ACCEPT p_oldserial PROMPT 'Enter Old Serial: ';
ACCEPT p_newserial PROMPT 'Enter New Serial: ';
INSERT INTO car
(SELECT serial, cname, make, model, year, color, trim, enginetype, purchinv, purchdate, purchfrom, purchcost, freight, totalcost, listprice
FROM customer
WHERE serial='&p_oldserial');
UPDATE saleinv
SET serial='&p_newserial'
WHERE serial='&p_oldserial';
UPDATE serivceinv, saleinv;
DELETE FROM customer
WHERE serial='&p_oldserial';
COMMIT;
但我得到的是ORA-02291。我在剧本中犯了什么错误吗?
答案 0 :(得分:2)
你的问题是“我的剧本中是否犯了错误?”。
答案是“是的,非常肯定”,但也许不是你想的那样。这不是语法错误,修复起来很简单。这是一个逻辑和理解问题,处理起来要困难得多。
主键有三个基本属性:
你试图违反规则#3。现在,在所有其他条件相同的情况下,Oracle(以及我曾经使用过的所有其他关系数据库)都会让您随意违反规则#3。但是,在这种情况下,还有另一个表格带有FOREIGN KEY约束,该约束引用了您尝试更改的主键。在UPDATE语句执行Oracle之后,然后检查可能受影响的所有外键约束,并发现其中一个被违反,因为'parent'表中的键值不再存在于'parent'表中(SALEINV)在这种情况下的表)。
此时常见的反应是说,“愚蠢的数据库!关系数据库显然已经破了!我非常聪明!!外键约束很糟糕,必须要消除!!!” 。因此,开发人员愤怒地从悬崖上行进,删除像疯子一样的外键,并想知道为什么会有这样的风,无论如何。我的意思是,有什么...< SPLAT!>?
事实上,外键约束刚刚让你无法做出真正的事情,真的很糟糕 - 事实上,这看起来很糟糕,看起来好像在做一些非常好的事情,但是没有,老实说,从我这里拿走它,改变一个主要的关键是一件非常糟糕的事情。 (不要问我怎么知道...... :-)。那个主键是让你知道有问题的行总是永远都是同一个东西的一件事,如果你改变了它,你会说“这件事以前是ABC现在是XYZ,现在它所指的任何地方都必须指的是作为XYZ“。在你的数据库中将它想象为“身体抢夺者的入侵” - 一旦你开始这样做,你再也不能相信任何东西会保持原样,你不能安全地将任何行与任何其他行相关联,因为键可能会改变,你不能强制执行关系完整性,而且......当你开始处理所有“丢失的记录”,“缺少父记录”,“缺少数据”和相关问题时,你的生活会很快变得非常有趣。 / p>
最终分析 - 找出其他方法来做你想做的事。除此之外,你真的建议你改变车辆上的VIN吗?这是另一件坏事,我怀疑有很多执法机构愿意解释为什么......: - )
分享并享受。
答案 1 :(得分:1)
第一个问题是哪个陈述失败了。一次执行脚本一个语句。我希望它是DELETE语句。
DELETE FROM customer
WHERE serial='&p_oldserial';
如果是这样,您没有使用外键移动引用此行的所有记录。第二次更新是否应该阅读?
UPDATE serviceinv
SET serial='&p_newserial'
WHERE serial='&p_oldserial';
是否有其他表需要类似的更新?
正如其他人所说,主键通常被认为是不可变的。因此,这应该是一次性改变。如果这可能是一个频繁的变化,那么您可能需要一个代理键。这会将更新减少到:
UPDATE car
SET serial='&p_newserial'
WHERE serial='&p_oldserial';
如果这可能是经常更改而您无法添加代理键,请查看CASCADE选项。