UPDATE con JOIN en ORACLE

3 replies [Último envío]
does not have a status.
User offline. Last seen 1 año 35 semanas ago. Offline
Joined: 12/09/2006
puntos: 10
Versión para impresión

Supongamos que queremos actualizar en nuestra bbdd ORACLE el campo de costes de la tabla de hechos FAC_TABLE con el coste unitario de nuestra tabla de COSTES.

Podemos hacerlo de dos maneras:

1. (Lenta, pero si es para pocos datos o para lanzarlo esporádicamente nos puede valer)

update FAC_TABLE ft
set COSTE_UNITARIO = (select distinct COSTE_UNITARIO  from COSTES ct 
 where (ft.id_articulo = ct.id_articulo);

2. (la mejor manera es esta, y el rendimimento es óptimo si tiene constraints)

UPDATE (
 SELECT 
   ft.COSTE_UNITARIO AS old_coste,
   ct.COSTE_UNITARIO AS new_coste
 FROM FAC_TABLE ft
 INNER JOIN COSTES ct ON ft.id_articulo = ct.id_articulo)
)
SET old_coste = new_coste;

Para que esta segunda oción funcione necesitamos tener UNIQUE or PRIMARY KEY constraint en ct.id_articulo.
Si no tienes esta constraint, puedes utilizar el hint /*+BYPASS_UJVC*/ después de la palabra UPDATE
(bypass update join view constraint).

El rendimiento aumenta si tenemos la constraint pero aún sin ella debe correr mucho más que la primera opción.

Espero que os ayude.

Héctor Minguet.

Preparando imágenes virtuales de VMWare ESXi para hacer pruebas de software en mi servidor
Imagen de carlos
User offline. Last seen 4 horas 33 mins ago. Offline
Joined: 28/12/2005
puntos: 260

He tenido la oportunidad de probar este tipo de update con tablas grandes, de varios millones de registros, y realmente funciona como comentas.
He lanzado un update con la primera opción y he decidido cancelarlo cuando he visto que comenzaba a afectar negativamente al rendimiento de la base de datos. El tiempo estimado que me daba la consola de Enterprise Manager para terminar era de 1 hora y media.

Después de cancelar he probado la segunda opción y me he encontrado con el error ORA-01779 porque no tenía una clave única definida sobre el campo de la tabla con la que hacía la join. Como la tabla era demasiado grande para crear un índice único sin estudiarlo primero, he probado la opción de incluir el hint /*+BYPASS_UJVC*/ (para hacer esto hay que asegurarse antes de que la correspondencia es realmente de 1:1, si no podemos obtener resultados inesperados), y el update se ha realizado correctamente en menos de 15 minutos, una diferencia considerable.

Ahora a ver si alguien se anima y nos cuenta la mejora que se obtiene con la segunda opción, pero creando una clave única en la tabla 'enlazada', y sin utilizar el hint.

Maricela (no verificado)

Hola se agradece este  bypass , justamente tenia que actualizar unas tablas que tenian correlativos repetidos y tenian que ser secuencial, realice una tabla temporal y despues aplicar un update, de igual forma tenia que hace un procedimiento almacenado pero en fin... con este bypass, todo bien.  el tiempo de respuesta en la actualizacion el descuebe GRACIAS!!! 

gracias.

atte.

Maricela de CHILE

Luis H (no verificado)

Gracias.

Lo utilice para una actualizacion de varios campos y se comporto de maravilla.