2015-11-03 80 views
0

如果我有两个表和第三个表是外键的第一个和第二个表如下:的SQLite上删除级联两个外键

CREATE TABLE A 
(
    name VARCHAR(255), 
    PRIMARY KEY(name) 
); 

CREATE TABLE B 
(
    number INT, 
    PRIMARY KEY(number) 
); 

CREATE TABLE C 
(
    cname VARCHAR(255), 
    cnumber INT, 
    PRIMARY KEY(cname, cnumber), 
    FOREIGN KEY(cname) REFERENCES A(name) ON DELETE CASCADE, 
    FOREIGN KEY(cnumber) REFERENCES B(number) ON DELETE CASCADE 
); 

INSERT INTO A values("John"); 
INSERT INTO A values("Sam"); 
INSERT INTO B values(1); 
INSERT INTO B values(2); 
INSERT INTO C values("John", 1); 
INSERT INTO C values("John", 2); 
INSERT INTO C values("Sam", 2); 

我想删除1这样(1)从B中删除,条目(John,1)也从C中删除,A中的(John)也被删除。

因为有DELETE CASCADE我应该能够做到这一点,但:

DELETE FROM B WHERE number = 1; 

只能在C中删除的B 1(John,1)(John)在一个不会被删除。

到目前为止,我只能从1个表中删除一个条目,并让其他表使用外键删除它的条目,但我不知道如何删除另外一个表,这个表也引用了这个表键与JUST 1查询。

回答

2

想要达到的效果是不可能使用外键的,至少不是你设置它的方式。

CA外键,所以从C作品将于如果A相应的键被删除,而不是其他的方式去除。 如果您想从A中删除当C中的条目被删除时,A需要在C上有外键。

这要求,那cname将是C一个独特的密钥。 Sqlite将允许你设置和插入数据,但是如果有多个条目被引用为外键,它将不允许你删除。

PRAGMA foreign_key = true; 
CREATE TABLE B 
(
    number INT, 
    PRIMARY KEY(number) 
); 

CREATE TABLE C 
(
    cname VARCHAR(255), 
    cnumber INT, 
    PRIMARY KEY(cname, cnumber), 
    FOREIGN KEY(cnumber) REFERENCES B(number) ON DELETE CASCADE 
); 

CREATE TABLE A 
(
    name VARCHAR(255), 
    PRIMARY KEY(name) 
    FOREIGN KEY(name) REFERENCES C(came) ON DELETE CASCADE 
); 

INSERT INTO B values(1); 
INSERT INTO B values(2); 
INSERT INTO C values("John", 1); 
INSERT INTO C values("John", 2); 
INSERT INTO C values("Sam", 2); 
INSERT INTO A values("John"); 
INSERT INTO A values("Sam"); 

INSERT INTO C values("John", 1); 
INSERT INTO C values("John", 2); 
INSERT INTO C values("Sam", 2); 

DELETE FROM B where number = 1; 
Error: foreign key mismatch - "A" referencing "C" 
+0

你是说,如果C引用了A和B,我可以在删除的东西,删除用C的东西,并分别删除B中的东西,删除用C的东西,但没有一个查询,可以删除的东西在所有三张桌子里一起? (这是我打算做的) – maregor

+0

我不打算改变表格结构,因为这是作业的一部分。我只是想知道是否有可能在1个查询中执行一个删除操作,这个删除操作包括从A,B和C中删除问题中的当前结构。 – maregor

+0

有两个问题:首先,从B中删除后,C中仍然存在一个“John”,所以基本上,如果不违反使用'(John,2)'的外键约束,就不能从A中删除它。其次,顾名思义,外键需要引用_key_,所以简单地颠倒模式就像我在上面的例子中所做的那样是行不通的。我甚至对SQLite允许我在非关键字上设置外键引用感到惊讶。但是,嘿,SQLite中的外键支持是可选的,如果您忘记在每个连接上打开PRAGMA,则根本不会检查外键。 –