2008-11-07 11 views
1

J'ai fondamentalement créé quelques tables pour jouer avec: J'ai deux tables principales, et une table de jointure Many-Many. Voici le DDL: (J'utilise HSQLDB)SQL: suppression complexe

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

Je veux créer une déclaration de suppression qui supprime les orphelins du (s'il existe une seule entrée dans la table de jointure pour un travail spécifique) en fonction de la personne .PERSON_ID.

En pseudo langue:

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

Où X est une person_id. J'ai essayé beaucoup de manières différentes; Je pense que c'est la partie "COUNT" qui cause des problèmes. Je suis une recrue SQL, donc toute aide serait très appréciée.

+0

Je ne suis pas tout à fait clair sur la question. Les orphelins de la table de travail n'auraient pas d'entrée correspondante dans la table job_person. – Dave

+0

Selon Dave, je ne comprends pas pourquoi vous essayez de supprimer des données qui sont utilisées par une autre table ... – Fred

+0

Ceci est la fonctionnalité que je cherchais: SUPPRIMER DE TRAVAIL OÙ JOB_ID PAS ( SELECT JOB_ID FROM JOB_PERSON ) – systemoutprintln

Répondre

2

Je ne suis pas.

Vous ne pouvez pas supprimer JOB lignes qui ont JOB_PERSON lignes (même une seule) en raison de vos contraintes FK. Il n'y a donc aucun moyen de supprimer JOB lignes basées sur PERSON lignes.

JOB_PERSON lignes doivent être supprimées avant de pouvoir supprimer JOB ou PERSON.

Si vous voulez supprimer toutes les JOB lignes sans JOB_PERSON, puis d'une manière est:

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

Si vous voulez supprimer toutes JOB_PERSON lignes pour une personne en particulier, puis tous les orphelins, le font en deux étapes :

DELETE FROM JOB_PERSON 
WHERE PERSON_ID = X 

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

Si vous voulez supprimer uniquement l'orphelin JOB s précédemment lié à X, vous devez tenir ceux d'une table temporaire avant la première supprimer.

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

"Les lignes JOB_PERSON doivent être supprimées avant de pouvoir supprimer un TRAVAIL ou une PERSONNE." - pas quand ON DELETE CASCADE a été utilisé, comme il a ici. –

+0

À droite, il va quitter les orphelins d'une manière ou d'une autre. Je vais mettre à jour le code. –

1

Ceci supprimera de votre table les entrées JOB qui n'ont pas d'entrée dans la table JOB_PERSON (Orpheans).

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

Vous ne pouvez pas supprimer des lignes qui sont liés par un étranger sur une autre table ...

+0

Je pense que vous vouliez dire "NOT IN" correct? – systemoutprintln