仅考虑到您拥有的表格,您无法做到这一点。但这并不是说它不能完成。 :-)
理想情况下,您应该将 ORDER.PART 更改为 CHAR(50) 以匹配其他表上的 PARTS_NUM 字段 - 否则您将无法在 ORDER 中存储所有可能的 PARTS_NUM。可能有商业原因使它保持原样,也许有人只是一无所知。没关系 - 如果可以,请尝试修复它。不过,它不会完全阻止你。
创建另一个表 - 我们称之为 PARTS_ALL。它有两个字段 - PARTS_NUM 应该与 PARTS_INV 和 PARTS_NONINV 上的 PARTS_NUM 字段的数据类型匹配,而 SOURCE 应该是 VARCHAR2(1)。使 (PARTS_NUM, SOURCE) 的组合成为主键。所以看起来像
CREATE TABLE ALL_PARTS
(PARTS_NUM CHAR(50),
SOURCE VARCHAR2(1) NOT NULL,
CONSTRAINT PK_ALL_PARTS
PRIMARY KEY (PARTS_NUM, SOURCE));
然后将数据从 PARTS_INV 和 PARTS_NONINV 复制到 ALL_PARTS,并添加适当的 SOURCE 值:
INSERT INTO ALL_PARTS (PARTS_NUM, SOURCE)
SELECT PARTS_NUM, 'I' AS SOURCE FROM PARTS_INV
UNION ALL
SELECT PARTS_NUM, 'I' AS SOURCE FROM PARTS_NONINV
现在您在 PARTS_INV 和 PARTS_NONINV 上定义了几个触发器,以将这些表上的插入和删除传播到 ALL_PARTS:
CREATE TRIGGER PARTS_INV_AID
AFTER INSERT OR DELETE ON PARTS_INV
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO ALL_PARTS (PARTS_NUM, SOURCE) VALUES (:NEW.PARTS_NUM, 'I');
ELSIF DELETING THEN
DELETE FROM ALL_PARTS WHERE PARTS_NUM = :OLD.PARTS_NUM;
END IF;
END PARTS_INV_AID;
/
CREATE TRIGGER PARTS_NONINV_AID
AFTER INSERT OR DELETE ON PARTS_NONINV
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO ALL_PARTS (PARTS_NUM, SOURCE) VALUES (:NEW.PARTS_NUM, 'N');
ELSIF DELETING THEN
DELETE FROM ALL_PARTS WHERE PARTS_NUM = :OLD.PARTS_NUM;
END IF;
END PARTS_NONINV_AID;
/
现在您的应用程序套件可以像往常一样继续从 PARTS_INV 和 PARTS_NONINV 插入和删除行,并且这些更改将传播到 ALL_PARTS。
现在(终于!)您可以定义从 ORDERS 到 ALL_PARTS 的外键并获得所需的验证:
ALTER TABLE ORDER
ADD CONSTRAINT ORDER_FK1
FOREIGN KEY (PART) REFERENCES ALL_PARTS (PARTS_NUM);
这是理想的吗?不。理想情况下,您会摆脱 PARTS_INV 和 PARTS_NONINV,并用 ALL_PARTS 替换它们,修改所有应用程序和 Web 应用程序和后台软件以使用新表 - 所以可能不会发生 - 但考虑到您自己发现的情况在它可能和你能做的一样好。
dbfiddle here