在DB2中,假设我有3个表:T1,T2,T3:
CREATE TABLE T1 (
T1_ID INTEGER NOT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE T2 (
T2_T1 INTEGER NOT NULL, -- parent entity ID from T1
T2_ID INTEGER NOT NULL,
PRIMARY KEY (T2_T1, T2_ID),
);
CREATE TABLE T3 (
T3_T1 INTEGER NOT NULL, -- parent entity ID from T1
T3_T2 INTEGER NOT NULL, -- parent entity ID from T2
T3_ID INTEGER NOT NULL,
PRIMARY KEY (T3_T1, T3_T2, T3_ID)
);
我想以某种方式定义FK关系,如果在T3中有连接记录,它将禁止删除T2中的记录,但同时当我从T1删除记录时,它应该自动删除T2中的记录和T3分别。
是否可以定义FK约束来满足这些要求?或者,如果没有编写首先从T3中删除适当的记录记录的代码,然后从T2中删除,然后才从T1中删除它,就无法实现?
更新:我正在尝试运行的实际 DB2 10.5 代码:
CREATE TABLE t1 (
t1_id INTEGER NOT NULL,
PRIMARY KEY(t1_id)
)
CREATE TABLE t2 (
t2_t1 INTEGER NOT NULL,
t2_id INTEGER NOT NULL,
PRIMARY KEY (t2_t1, t2_id),
CONSTRAINT t2_fk_t1
FOREIGN KEY (t2_t1)
REFERENCES t1 (t1_id)
ON DELETE CASCADE
)
CREATE TABLE t3 (
t3_t1 INTEGER NOT NULL,
t3_t2 INTEGER NOT NULL,
t3_id INTEGER NOT NULL,
PRIMARY KEY (t3_t1, t3_t2, t3_id),
CONSTRAINT t3_fk_t1
FOREIGN KEY (t3_t1)
REFERENCES t1 (t1_id)
ON DELETE CASCADE,
CONSTRAINT t3_fk_t2
FOREIGN KEY (t3_t1, t3_t2)
REFERENCES t2 (t2_t1, t2_id)
ON DELETE RESTRICT
)
最后一个CREATE
语句失败,并显示以下错误:
SQL20255N FOREIGN KEY“T3_FK_T2”无效,因为它会导致 要删除连接到其祖先表的后代表“S.T3” “S.T1”通过与冲突删除规则的多种关系。 冲突是在约束的删除规则之间 后代表上的“S.T3.T3_FK_T1”和“S.T3.T3_FK_T2”。 原因代码=“3”。 SQLSTATE = 42915
答案 0 :(得分:0)
这应该有效。即使它看起来有点奇怪,也不禁止重叠约束。
CREATE TABLE t1 (
t1_id INTEGER NOT NULL PRIMARY KEY
);
CREATE TABLE t2 (
t2_t1 INTEGER NOT NULL REFERENCES t1(t1_id) ON DELETE CASCADE
, t2_id INTEGER NOT NULL
, PRIMARY KEY (t2_t1, t2_id)
);
CREATE TABLE t3 (
t3_t1 INTEGER NOT NULL REFERENCES t1(t1_id) ON DELETE CASCADE
, t3_t2 INTEGER NOT NULL
, FOREIGN KEY (t3_t1,t3_t2) REFERENCES t2(t2_t1,t2_id) ON DELETE RESTRICT
, t3_id INTEGER NOT NULL
, PRIMARY KEY (t3_t1, t3_t2, t3_id)
);
INSERT INTO t1 (t1_id) VALUES (11), (12),(13), (14), (15);
INSERT INTO t2 (t2_t1,t2_id) VALUES (11, 21), (12,22),(13,23), (14,24), (15,25);
INSERT INTO t3 (t3_t1,t3_t2,t3_id) VALUES (11, 21,31), (12,22,32),(13,23,33), (14,24,34), (15,25,35);
DELETE FROM t1 WHERE t1_id = 13; -- should succeed
DELETE FROM t2 WHERE t2_id = 24; -- should fail
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
答案 1 :(得分:0)
是的,这是可能的。
只需创建一个从T3到T2和T1的外键,T2是删除时的RESTRICT,T1没有动作。
在T2中,T1的外键也带有级联删除。
CREATE TABLE T1 (
T1_ID INTEGER NOT NULL unique,
PRIMARY KEY (T1_ID)
);
CREATE TABLE T2 (
T2_T1 INTEGER NOT NULL constraint t2_t1_t1_id_fk
references t1
on delete cascade, -- parent entity ID from T1
T2_ID INTEGER NOT NULL unique,
PRIMARY KEY (T2_T1, T2_ID)
);
CREATE TABLE T3 (
T3_T1 INTEGER NOT NULL constraint t3_t1_t1_id_fk
references t1
on delete cascade, -- parent entity ID from T1
T3_T2 INTEGER NOT NULL constraint t3_t2_t2_id_fk
references t2 (t2_id) on delete restrict, -- parent entity ID from T2
T3_ID INTEGER NOT NULL,
PRIMARY KEY (T3_T1, T3_T2, T3_ID)
);
请记住,如果您想拥有更严格的外键,您也可以从其他角度进行操作。 (从ID到引用的外键!)
最糟糕的情况是总有触发器,一切皆有可能。 :)