2008-11-07 2 views
1

В основном я создал несколько таблиц для игры: у меня есть две основные таблицы и таблица со многими из многих. Вот DDL: (я использую HSQLDB)SQL: Complex Deletion

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); 

Я хочу создать ВЕЬЕТЕ, который удаляет сирот из JOB (если существует только одна запись в соединительной таблице для конкретной работы) на основе ЛИЧНОСТИ .PERSON_ID.

В языке псевдо:

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, поэтому любая помощь была бы высоко оценена.

+0

Я не совсем ясно, по этому вопросу. Сироты в таблице заданий не будут иметь соответствующей записи в таблице job_person. – Dave

+0

По словам Дэйва я не понимаю, почему вы пытаетесь удалить данные, которые используются в другой таблице ... – Fred

+0

Это функциональность я искал: DELETE FROM JOB WHERE JOB_ID NOT IN (SELECT, JOB_ID ОТ JOB_PERSON ) – systemoutprintln

ответ

2

Я не следую.

Вы не можете удалить JOB строк, которые имеют JOB_PERSON строк (даже один) из-за ваших противопоказаний FK. Таким образом, нет способа удалить строки JOB на основе строк PERSON.

JOB_PERSON строки должны быть удалены перед удалением JOB или PERSON.

Если вы хотите удалить все JOB строки, без JOB_PERSON, то один способ:

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 
) 

Если вы хотите удалить только сирота JOB ы ранее связанный с X, вам нужно будет держать те во временной таблице до первого удаления.

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 
) 
+0

«Строки JOB_PERSON должны быть удалены, прежде чем удастся удалить JOB или PERSON». - не когда ON DELETE CASCADE используется, как здесь. –

+0

Правильно, он собирается оставить сирот так или иначе. Я обновлю код. –

1

Это удалит из ваших записей JOB таблицы, которые не имеют никаких записей в таблице JOB_PERSON (Orpheans).

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

Вы не можете удалять строки, которые связаны иностранцем на другой стол ...

+0

Я думаю, что вы имели в виду «НЕ В IN» правильно? – systemoutprintln