¿Cómo puede SQL Delete usar una subconsulta?


15

El siguiente código fue agregado por uno de nuestros desarrolladores para eliminar registros duplicados de la tabla:

DELETE  SubQuery

FROM
(
    SELECT  ID
            ,FK1
            ,FK2
            ,CreatedDateTime
            ,ROW_NUMBER() OVER(PARTITION BY FK1, FK2 ORDER BY CreatedDateTime) AS RowNumber

    FROM    Table
)
AS SubQuery

WHERE   RowNumber > 1

Al revisar el código, supuse que no funcionaría, sin embargo, probarlo en nuestro entorno de prueba (SQL 2014) muestra que sí.

¿Cómo sabe SQL para resolver la subconsulta y eliminar los registros table?

Respuestas:


14

Lo subqueryque tienes en tu código se llama tabla derivada . No es una tabla base, sino una tabla que "vive" durante el tiempo que se ejecuta la consulta. Al igual que las vistas (que también se llaman tablas vistas ), y en versiones recientes CTE, que es otra cuarta forma de "definir" una tabla dentro de una consulta, son similares a una tabla en muchos aspectos. Puede selectpartir de ellos, se puede utilizar en fromo para joinellos a otras tablas (base o no!).

En algunos DBMS, (no todos los DBMS han implementado esto de la misma manera) estas tablas / vistas son actualizables . Y "actualizable" significa que también podemos update, desde inserto deletehacia ellos.

Sin embargo, existen restricciones y esto se espera. Imagine si subqueryse tratara de una unión de 2 (o 17 tablas). ¿Qué deletesignificaría entonces? (¿de qué tablas se deben eliminar las filas?) Las vistas actualizables son un asunto muy complicado . Hay un libro reciente (2012), enteramente sobre este tema, escrito por Chris Date, conocido experto en teoría relacional: Ver actualización y teoría relacional .

Cuando la tabla derivada (o vista) es una consulta muy simple, como si tuviera solo una tabla base (posiblemente restringida por a WHERE) y no GROUP BY, entonces cada fila de la tabla derivada corresponde a una fila en la tabla base subyacente, por lo que es fácil * para actualizar, insertar o eliminar de esto.

Cuando el código dentro de la subconsulta es más complejo, depende de si las filas de la tabla / vista derivada se pueden rastrear / resolver en filas desde una de las tablas base subyacentes.

Para SQL Server, puede leer más en el párrafo vistas actualizables en MSDN: CREATE VIEW.

Vistas actualizables

Puede modificar los datos de una tabla base subyacente a través de una vista, siempre que se cumplan las siguientes condiciones:

  • Cualquier modificación, incluidas UPDATE, INSERTy DELETEdeclaraciones, debe hacer referencia a columnas de una sola tabla base.

  • Las columnas que se modifican en la vista deben hacer referencia directamente a los datos subyacentes en las columnas de la tabla. Las columnas no se pueden derivar de ninguna otra manera, como a través de lo siguiente:

  • Una función agregada: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR, y VARP.

  • Un cómputo La columna no se puede calcular a partir de una expresión que usa otras columnas. Las columnas que se forman mediante el uso de los operadores de conjuntos UNION, UNION ALL, CROSSJOIN, EXCEPT, y INTERSECT cantidad para un cálculo y también no son actualizables.

  • Las columnas están modificando no están afectados por GROUP BY, HAVINGo DISTINCTcláusulas.

  • TOPno se usa en ninguna parte de la selección de la vista junto con la WITH CHECK OPTIONcláusula.

Las restricciones anteriores se aplican a cualquier subconsulta en la FROMcláusula de la vista, tal como se aplican a la vista misma. En general, el Motor de base de datos debe poder rastrear sin ambigüedades las modificaciones de la definición de vista a una tabla base.


En realidad deletees más fácil, menos complejo que update. SQL Server solo necesita las claves primarias o alguna otra forma de identificar qué filas de la tabla base se eliminarán. Para update, hay una restricción adicional (bastante obvia) que no podemos actualizar una columna calculada. Puede intentar modificar su consulta para hacer una actualización. La actualización CreatedDateTimeprobablemente funcionará bien, pero intentar actualizar la RowNumbercolumna calculada generará un error. Y insertes aún más complejo, ya que tendríamos que proporcionar valores para todas las columnas de la tabla base que no tienen una DEFAULTrestricción.


4

Es fácil de ver cuando observa el plan de consulta. En su caso, el plan solo contiene un operador adicional de Segmento y Proyecto de secuencia para manejar el número de fila. Este tipo de operación solo funciona cuando SQL Server realmente puede resolver la tabla subyacente.

La eliminación de subconsultas y CTE es totalmente compatible y muy eficiente, particularmente para eliminar duplicados. También parece recordar haberlo usado en versiones anteriores de SQL Server.

Más en una vieja publicación de blog mía.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.