【问题标题】:SQL: Complex DeletionSQL:复杂删除
【发布时间】:2010-09-21 07:02:57
【问题描述】:

我基本上创建了一些表来玩:我有两个主表和一个多对多连接表。这是 DDL:(我正在使用 HSQLDB)

CREATE TABLE PERSON
(
    PERSON_ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, 
    NAME VARCHAR(50), MAIN_PERSON_ID INTEGER
)

CREATE TABLE JOB
(
    JOB_ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, 
    NAME VARCHAR(50)
)
CREATE TABLE JOB_PERSON
(
    PERSON_ID INTEGER, 
    JOB_ID INTEGER
)
ALTER TABLE JOB_PERSON ADD 
    CONSTRAINT FK_PERSON_JOB FOREIGN KEY(PERSON_ID) 
    REFERENCES PERSON ON DELETE CASCADE ON UPDATE CASCADE 

ALTER TABLE JOB_PERSON ADD
    CONSTRAINT FK_JOB_PERSON FOREIGN KEY(JOB_ID) 
    REFERENCES JOB ON DELETE CASCADE ON UPDATE CASCADE

ALTER TABLE PERSON ADD
    CONSTRAINT FK_PERSON_PERSON FOREIGN KEY(MAIN_PERSON_ID) 
    REFERENCES PERSON ON DELETE CASCADE ON UPDATE CASCADE

insert into person values(null,'Arthur', null);
insert into person values(null,'James',0);
insert into job values(null, 'Programmer')
insert into job values(null, 'Manager')
insert into job_person values(0,0);
insert into job_person values(0,1);
insert into job_person values(1,1);

我想创建一个删除语句,根据 PERSON.PERSON_ID 从 JOB 中删除孤儿(如果特定作业的连接表中只存在一个条目)。

伪语言:

delete from job where job_person.job_id=job.job_id 
AND count(job_person.job_id)=1 AND job_person.person_id=X

其中 X 是一些 person_id。我尝试了很多不同的方法;我认为这是导致问题的“COUNT”部分。我是 SQL 菜鸟,所以任何帮助将不胜感激。

【问题讨论】:

  • 我对这个问题并不完全清楚。作业表中的孤儿在 job_person 表中没有对应的条目。
  • 根据戴夫的说法,我不明白您为什么要尝试删除其他表使用的数据...
  • 这是我正在寻找的功能:DELETE FROM JOB WHERE JOB_ID NOT IN (SELECT JOB_ID FROM JOB_PERSON)
  • 啊哈。你应该选择一个答案@Cade Roux's 是最彻底的。

标签: sql count hsqldb


【解决方案1】:

我没有关注。

由于您的 FK 约束,您无法删除具有 JOB_PERSON 行(甚至是一个)的 JOB 行。因此无法根据PERSON 行删除JOB 行。

必须先删除JOB_PERSON 行,然后才能删除JOBPERSON

如果您想删除所有没有JOB_PERSONJOB 行,那么一种方法是:

DELETE FROM JOB
WHERE JOB_ID NOT IN (
    SELECT JOB_ID
    FROM JOB_PERSON
)

如果要删除特定人员的所有 JOB_PERSON 行,然后删除所有孤儿,请分两步进行:

DELETE FROM JOB_PERSON
WHERE PERSON_ID = X

DELETE FROM JOB
WHERE JOB_ID NOT IN (
    SELECT JOB_ID
    FROM JOB_PERSON
)

如果您只想删除之前链接到 X 的孤立 JOBs,则需要在第一次删除之前将它们保存在临时表中。

INSERT INTO TEMP_TABLE
SELECT JOB.JOB_ID
FROM JOB
INNER JOIN JOB_PERSON
    ON JOB_PERSON.JOB_ID = JOB.JOB_ID
WHERE JOB_PERSON.PERSON_ID = X

DELETE FROM PERSON
WHERE PERSON_ID = X

-- YOUR CASCADING DELETE DOES THIS:
/*
DELETE FROM JOB_PERSON
WHERE PERSON_ID = X
*/

-- Now clean up (only) new orphans on the other side
DELETE FROM JOB
WHERE JOB_ID NOT IN (
    SELECT JOB_ID
    FROM JOB_PERSON
)
AND JOB_ID IN (
    SELECT JOB_ID
    FROM TEMP_TABLE
)

【讨论】:

  • "必须先删除 JOB_PERSON 行,然后才能删除 JOB 或 PERSON。" - 不是在使用 ON DELETE CASCADE 时,就像这里一样。
  • 对,他会以这样或那样的方式离开孤儿。我会更新代码。
【解决方案2】:

这将从您的表 JOB 条目中删除,这些条目在表 JOB_PERSON(Orpheans)中没有条目。

DELETE FROM JOB
WHERE JOB_ID NOT IN (
    SELECT JOB_ID
    FROM JOB_PERSON
)

您不能删除由其他表上的外部链接的行...

【讨论】:

    猜你喜欢
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 2011-06-06
    • 2020-04-22
    相关资源
    最近更新 更多