Вопрос
Я в основном создал несколько столов, с которыми можно поиграться: у меня есть два основных стола и стол соединения многих-многих. Вот 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);
Я хочу создать оператор удаления, который удаляет сирот из JOB (если существует только одна запись в таблице соединений для определенного задания) на основе PERSON.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, поэтому любая помощь будет принята с благодарностью.
Решение
Я не следую.
Вы не можете удалить строки 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
)
Другие советы
Это удалит из вашей таблицы записи JOB, которые не имеют записей в таблице JOB_PERSON (Orpheans).
DELETE FROM JOB
WHERE JOB_ID NOT IN (
SELECT JOB_ID
FROM JOB_PERSON
)
Вы не можете удалить строки, которые связаны посторонним в другой таблице ...