¿Usar CASO para seleccionar columnas en la consulta ACTUALIZAR?

13

Puedo usar CASEpara elegir qué columnas mostrar en una SELECTconsulta (Postgres), así:

SELECT CASE WHEN val = 0 THEN column_x
            WHEN val = 1 THEN column_y
            ELSE 0
       END AS update, ...

¿Es posible algo similar al realizar una UPDATEconsulta en Postgres (es decir, elegir qué columnas deben actualizarse)? Supongo que no, ya que no pude encontrar nada al respecto, pero tal vez alguien tiene una alternativa inteligente (además de usar un procedimiento o actualizar cada columna usando a CASEpara determinar si el valor de la columna debe asignarse a un nuevo valor o simplemente reasignar el existente valor). Si no hay una alternativa fácil, por supuesto, también lo aceptaré como respuesta.

Información adicional : en mi caso, tengo 14 columnas potenciales que pueden actualizarse, y solo una se actualiza por fila coincidente (la tabla que se actualizará se une con otra en la consulta). La cantidad de filas para actualizar probablemente variará, podría ser decenas o cientos. Creo que existen índices para las condiciones de unión.

Newenglander
fuente

Respuestas:

26

Si especifica que una columna debe actualizarse, siempre se actualizará, pero puede cambiar el valor que ingresó condicionalmente y volver a colocar los valores originales según sus condiciones. Algo como:

UPDATE some_table
SET    column_x = CASE WHEN should_update_x THEN new_value_for_x ELSE column_x END
     , column_y = CASE WHEN should_update_y THEN new_value_for_y ELSE column_y END
     , column_z = CASE WHEN should_update_z THEN new_value_for_z ELSE column_z END
FROM   ...

Entonces, si las condiciones no son adecuadas para una actualización de una columna en particular, simplemente retroalimente su valor actual.

Ten en cuenta que cada fila coincidente se vea una actualización (incluso si todas las columnas terminan recibiendo conjunto de los valores que ya tienen) a menos que explícitamente puerta de esta circunstancia en la que el filtrado y dónde cláusulas, lo que podría ser un problema de rendimiento (no se sea ​​una escritura, los índices se actualizarán, los disparadores apropiados se dispararán, ...) si no se mitigan.

David Spillett
fuente
Gracias por el consejo sobre todo lo que se está actualizando, si esto es lento, puedo tomar la sugerencia de @Colin 't Hart de tener varias declaraciones de actualización.
newenglander
Puede mitigar ese problema completo asegurándose de que sus cláusulas ON y WHERE filtren todas las filas donde no se necesitan cambios, pero eso puede significar repetir todas sus condiciones tanto en la cláusula SET como en la cláusula WHERE (a menos que haya una verificación general más simple de que es 100% equivalente a todas esas condiciones combinadas). En ese punto, este método aún puede ser más eficiente, pero el método de actualizaciones múltiples puede ser más fácil de mantener.
David Spillett el
Tenga en cuenta también que actualizar una columna con el mismo valor hará que se cree rehacer, consulte orainternals.wordpress.com/2010/11/04/…
Colin 't Hart
@Colin: Sí, cualquier actualización pasará por el registro de transacciones de la base de datos, incluidas las actualizaciones que son esencialmente NoOps debido a que los campos de actualización tienen los mismos valores que tenían antes. Además de la posibilidad de un problema de rendimiento inmediato, este podría ser un factor importante si se usa la replicación, las copias de seguridad diferenciales, el envío de registros, etc., ya que las operaciones adicionales de actualización de filas aumentarán el espacio / ancho de banda necesario para ellos.
David Spillett el
Gracias a ambos por los consejos, en mi caso, la declaración de actualización única funcionó bien.
newenglander
5

¿Cuántas combinaciones diferentes de columnas para actualizar tienes? ¿Cuántas filas de toda la tabla se actualizarán? ¿Existen índices para un acceso rápido a las filas para actualizar?

Dependiendo de las respuestas a estas preguntas, es posible que pueda ejecutar varias declaraciones de actualización, una para cada columna que desea actualizar y colocar la condición en el valor de esa columna en la cláusula where de la actualización para que las filas cero se actualicen si esa columna tiene el valor incorrecto

Intente y piense en conjuntos, no asuma que la actualización necesita actualizar una sola fila encontrada por la clave primaria.

Colin 't Hart
fuente
Gracias por la respuesta. He agregado más información a mi pregunta, espero que sea comprensible. Esa es una buena alternativa con múltiples declaraciones de actualización (preferiría una declaración de actualización, pero veo que hay una ventaja allí).
newenglander
Esta puede ser la respuesta que estoy buscando, pero ¿te refieres a poner la actualización column_x = new_value_for_x donde @val = 0. Puedo experimentar con algo así. Parece gracioso No es más fácil de hacer si val = 0 comienza la actualización column_x = new_value_for_x, etc.
CashCow el
-1
update Practicing  -- table you will be updating
 set email = case -- column you will be updating
    when FName = 'Glenn' then '[email protected]'
       when FName = 'Riddick' then '[email protected]'
       when FName = 'Jeffrey' then 'sorcerer@wizcom'
       else email
    end
usuario134695
fuente
Esto actualiza solo una columna, mientras que el autor de la pregunta quiere saber cómo actualizar diferentes columnas según las condiciones.
Colin 't Hart