2009-02-02 9 views
23

quiero hacer algo como:Oracle borrar los registros coincidentes en múltiples valores

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

Sin embargo, parece que sólo se puede utilizar una columna con el operador IN. ¿Es eso cierto? Parece que una consulta como esta debería ser posible.

Respuesta

41

No, sólo necesita paréntesis: parens

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

Así que esto es en realidad engañosa y yo diría esencialmente incorrecto para la profundidad no intuitivo es. Si su fila contiene valor nulo, IN no funciona. Lo cual, supongo, tiene sentido por lo nulos que son, pero es completamente inconsistente con, por ejemplo, cómo funciona el menos. –

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

poner alrededor de sus términos en la cláusula where. ¡Aclamaciones!

2

La sintaxis siguiente funciona en SQL Server pero creo que es un estándar SQL pero como se ha señalado en los comentarios de esta aplicación es no estándar y no se admite actualmente en Oracle.

lo dejaré para referencia

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

No, SQL estándar solo admite una tabla en ELIMINAR. MySQL y Microsoft SQL Server admiten DELETE multi-tabla como una extensión del estándar, pero Oracle no lo hace. –

+0

El concepto estándar SQL de una tabla no está estrictamente limitado a una tabla. A menudo incluye vistas. Algunas vistas son actualizables y, por extensión, eliminable. –

+0

Gracias por los comentarios, es bueno aprender sobre las diferencias en las implementaciones de DB. He actualizado mi respuesta para incluir sus puntos – kristof

3

En Oracle, se puede hacer una eliminación desde un punto de vista en línea, pero por lo general necesita una clave externa que asegura que una fila de la tabla de la que el la fila se elimina no puede ser representada por más de una fila en la vista.

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

También puede utilizar la cláusula EXISTS:

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

+1; DONDE EXISTE es un mecanismo lamentablemente infravalorado, mucho mejor que el uso de IN – Brian

+1

@Brian: (¡Me doy cuenta de que estoy un poco retrasado respondiendo a tu comentario!) ¿Por qué dices que EXISTS es mucho mejor que IN? –

+1

Una muy buena pregunta. Tengo entendido que es una buena opción en términos de rendimiento, sin embargo, tengo poco que ofrecer en términos de evidencia. Dicho esto, he logrado encontrar esto: http://www.techrepublic.com/article/oracle-tip-understand-the-difference-between-in-and-exists-in-subqueries/5297080 – Brian

3

Tenga en cuenta que si los atributos son nulos, la fila de no considerados en. Es decir, si los cursos son iguales y tanto el estudiante como el programa principal son nulos, la fila no se eliminará.

Si un atributo, como importante, puede ser nula, y que desea nula = null para ser verdad, tratar:

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