2011-03-21 15 views
35

Tengo una secuencia de comandos que usa una pila de cláusulas with para obtener algún resultado, y luego quiero escribir ese resultado en una tabla. Simplemente no puedo entenderlo, ¿podría alguien apuntarme en la dirección correcta?Actualizar instrucción usando la cláusula

Aquí está un ejemplo simplificado que indica lo que quiero hacer:

with comp as (
    select *, 42 as ComputedValue from mytable where id = 1 
) 
update t 
set  SomeColumn = c.ComputedValue 
from mytable t 
     inner join comp c on t.id = c.id 

Lo real tiene un buen número de cláusulas que hagan referencia a unos de otros, por lo que cualquier sugerencia utilizando realmente la cláusula with sería altamente preferible sobre refactorizarlo a subconsultas anidadas.

Gracias de antemano,

Gert-Jan

+2

su información: Usted no tiene que editar el título y pregunta al señalar que su respuesta es sí mismo. Simplemente agregue su solución como su propia respuesta y selecciónela si es la mejor. –

+0

Ok, no puedo marcarlo como respondido todavía. ¡Gracias! – gjvdkamp

+0

estaba buscando una respuesta también y la encontré aquí: http://stackoverflow.com/questions/7030699/oracle-sql-update-with-data-from-aother-table – Bogdan

Respuesta

36

Si alguien viene aquí detrás de mí, esta es la respuesta que funcionó para mí.

update mytable t 
set z = (
    with comp as (
    select b.*, 42 as computed 
    from mytable t 
    where bs_id = 1 
) 
    select c.computed 
    from comp c 
    where c.id = t.id 
) 

Buena suerte,

GJ

+3

¿No actualizará esto todas las filas? Si hay filas donde c.id <> t.id, ¿no se establecerán en nulo? ¿Alguien sabe una manera de poner esa cláusula where afuera también? –

+0

No uses Oracle nunca más y esto fue hace un tiempo. Pruébalo y cuéntanos ;-) IIRC esto funcionó para mí. – gjvdkamp

+0

@gjvdkamp funciona igual que Sanjay Nambiar dijo: la actualización funciona en filas seleccionadas, pero todas las demás filas que están fuera de "donde" están establecidas en nulo. [2] ¿Alguien sabe una manera de poner esa cláusula where fuera también? – robsonrosa

24

El CON sintaxis parece ser válida en una vista en línea, por ejemplo

UPDATE (WITH comp AS ... 
     SELECT SomeColumn, ComputedValue FROM t INNER JOIN comp ...) 
    SET SomeColumn=ComputedValue; 

Sin embargo, en las pruebas rápidas Yo esto siempre ha fallado con ORA-01732: data manipulation operation not legal on this view, a pesar de que tuvo éxito si Reescribí para eliminar la cláusula. Por lo tanto, la refactorización puede interferir con la capacidad de Oracle para garantizar la preservación de claves.

Sin embargo, debería ser capaz de utilizar un MERGE. Usando el ejemplo sencillo que ha publicado esto ni siquiera requiere una cláusula WITH:

MERGE INTO mytable t 
USING (select *, 42 as ComputedValue from mytable where id = 1) comp 
ON (t.id = comp.id) 
WHEN MATCHED THEN UPDATE SET SomeColumn=ComputedValue; 

Pero entiendo que usted tiene una sub consulta más compleja que desea factorizar. Creo que podrá hacer la subconsulta en la cláusula USING arbitrariamente compleja, incorporando múltiples cláusulas WITH.

+1

Hola, muchas gracias por tu esfuerzo, Ya logramos que se ejecute. Las declaraciones con I que uso tienen bastantes niveles que calculan promedios y stddevs, luego usan que no normalizar (estadísticamente) los datos de otras tablas, etc. sería un verdadero dolor para la refactorización. El ejemplo fue solo la sintaxis de actualización. – gjvdkamp

Cuestiones relacionadas