2009-02-02 15 views
23

Ich möchte so etwas wie zu tun:Oracle Zeilen löschen Mehrere Werte Abstimmung Ein

jedoch
DELETE FROM student WHERE 
student.course, student.major IN 
(SELECT schedule.course, schedule.major FROM schedule) 

, so scheint es, dass Sie nur eine Spalte mit dem IN-Operator verwenden können. Ist das wahr? Scheint so, als ob eine Anfrage wie diese möglich sein sollte.

Antwort

41

Nein, Sie brauchen nur Klammern:

DELETE FROM student WHERE 
(student.course, student.major) IN 
(SELECT schedule.course, schedule.major FROM schedule) 
+0

Also das ist eigentlich irreführend ist, und ich würde im Wesentlichen falsch, wie tief nicht argumentieren intuitiv ist es. Wenn Ihre Zeile einen Nullwert enthält, funktioniert IN nicht. Was, denke ich, sinnvoll ist, wie Nullen sind, ist aber völlig inkonsequent mit zum Beispiel, wie Minus funktioniert. –

7
DELETE FROM student WHERE 
(student.course, student.major) IN 
(SELECT schedule.course, schedule.major FROM schedule) 

Put Pars um Ihre Bedingungen in der where-Klausel. Prost!

2

Die Syntax arbeitet unten in SQLServer aber ich glaube, es ist ein Standard-SQL- aber wie in den Kommentaren darauf hingewiesen, dies ist nicht Standard-Implementierung und wird derzeit nicht in Oracle unterstützt.

werde ich es als Referenz verlassen

delete s 
from 
    student s 
    inner join schedule sch 
    on s.course=sch.course 
    and s.major = sch.major 
+0

Nein, Standard-SQL unterstützt nur eine Tabelle in DELETE. MySQL und Microsoft SQL Server unterstützen DELETE mit mehreren Tabellen als Erweiterung des Standards, Oracle jedoch nicht. –

+0

Das SQL-Standardkonzept einer Tabelle ist nicht streng auf eine Tabelle beschränkt. Es enthält oft Ansichten. Bestimmte Ansichten sind aktualisierbar und dadurch löschbar. –

+0

Danke für die Kommentare, es ist gut, über Unterschiede in DB-Implementierungen zu lernen. Ich habe meine Antwort aktualisiert, um Ihre Punkte zu berücksichtigen – kristof

3

In Oracle können Sie ein von einer Inline-Ansicht tun löschen, aber es muss in der Regel einen Fremdschlüssel, dass eine Zeile aus der Tabelle stellt sicher, aus dem der Zeile ist gelöscht, kann nicht durch mehr als eine Zeile in der Ansicht dargestellt werden.

create table parent (id number primary key); 
create table child (id number primary key, parent_id number references parent); 
insert into parent values(1); 
insert into child values(2,1); 
delete from (select * from parent p, child c where c.parent_id = p.id); 
13

Sie könnten auch die EXISTS-Klausel verwenden:

DELETE FROM student WHERE 
EXISTS 
(
    SELECT 1 FROM schedule 
    WHERE schedule.course=student.course 
    AND schedule.major=student.major 
) 
+4

+1; WHERE EXISTS ist ein schlecht unterschätzter Mechanismus, viel besser als die Verwendung von IN – Brian

+1

@Brian: (Ich weiß, ich bin ein bisschen spät auf Ihren Kommentar reagieren!) Warum sagen Sie EXISTS ist viel besser als IN? –

+1

Eine sehr gute Frage. Mein Verständnis ist, dass es eine gute Wahl in Sachen Leistung ist, aber ich habe wenig in Bezug auf Beweise zu bieten. Das gesagt, ich habe es geschafft, dies zu finden: http://www.techrepublic.com/article/oracle-tip-understand-the-difference-between-in-and-exists-in-subqueries/5297080 – Brian

3

Beachten Sie, dass, wenn irgendwelche Attribute null sind, die Reihe der nicht in Betracht gezogen. Das heißt, wenn die Kurse gleich sind und sowohl der Student als auch der Hauptterminal null sind, wird die Zeile nicht gelöscht.

Wenn ein Attribut, wie Major, kann null sein, und Sie wollen null = null um wahr zu sein, versuchen Sie:

DELETE 
FROM student 
WHERE (student.course, NVL(student.major,'sOmeStRinG')) 
IN (SELECT schedule.course, NVL(schedule.major,'sOmeStRinG') FROM schedule) 
Verwandte Themen