UPDATE con JOIN en ORACLE

7 replies [Último envío]
Offline
Joined: 12/09/2006
Puntos: 19

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.

Imagen de carlos
Conectado
Joined: 28/12/2005
Puntos: 1208

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.

n/d
Maricela (no verificado)

Hola se agradece este bypass.

Justamente tenía que actualizar unas tablas que tenian correlativos repetidos y tenian que ser secuenciales, realicé una tabla temporal y despues aplicar un update. De igual forma tenia que hacer 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.

 

bardellica (no verificado)

Utilice un script con este hint /*+BYPASS_UJVC*/ y funciona una muy bien... Bajo un script de 9 hs a 6 segungos....
Pero cuando lo quiero utilizar dentro de un Package aparece un error "PL/SQL: ORA-01031: Insufficient privileges"
¿ALGUIEN PUEDE AYUDARME CON ESTE TEMA?

DESDE YA MUCHAS GRACIAS.

Marco (no verificado)

Bueno lo mas probable es que sea esto, mira una cosa son los permisos que tienes tu o tu usario y otra los permisos que tiene el paquete por ejemplo digamos que tu tienes el usuario au0001 y cuando corres esto si puedes hacerlo debido a tus permisos, pero cuando pones esto dentro del paquete que esta en el esquema au0002 y dicho esquema no tiene esos priviliegios, pues es claro que te truena aun si tu como usuario au0001 si tengas el permiso y seas tu el que corre el paquete , el paquete truena por ser el o su esquema mejor dicho el que no tiene los permisos.

Offline
Joined: 21/12/2009
Puntos: 10

Hola intente hacerlo de las dos maneras, el update tradicional y con el hint, con el primero se tarda bastante, lo cancele, con el segundo me marca el error ORA-01031 - Insufficient privileges, lo estoy haciendo en el mismo esquema, la tabla de la que quiero actualizar tiene llave unique en el campo que uso para unir con la tabla que tiene la información ¿A que se debe que con uno no me marque el error y con el segundo si?

Offline
Joined: 21/12/2009
Puntos: 10

¡¡¡ UPS !!! Perdón. Gracias por la ayuda.

Contenido relacionado

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

    UPDATE FAC_TABLE
    SET COSTE_UNITARIO = ct.COSTE_UNITARIO
    FROM COSTES ct
    WHERE FAC_TABLE.id_articulo = ct.id_articulo

     

    Algo más sencillo que en Oracle.

     

    Espero que os ayude.

    Héctor Minguet.

  • El error ORA-30926 suele producirse cuando se realizan operaciones Merge, y lo normal es que nos deje algo descolocados, ya que la descripción del mismo no da demasiada información sobre lo que está pasando:
    ORA-30926: unable to get a stable set of rows in the source tables.

    Normalmente este error se produce cuando en la operación Merge a una fila destino que hay que actualizar le corresponden más de una fila en la tabla origen. Como el motor no sabe qué registro escoger devuelve un error. Es un problema de duplicidad en la tabla origen...

  • Hola

     

    cordial saludo,

     

    bueno nuevamente con dudas y algunos problemas en el mapeo de datos.

     

    A ver tengo el siguente problema, he creado un mapa para el cual la tabla destino tiene un campo PK (secuencia)y tres campos me representan un constraint unique, para la asignacion del pk no se hace uso del NEXTVAL para obtener el ultimo valor de la secuencia. Para esto sean definido los valores de secuencia 

    en una tabla tabla_secuencia. el problema se me esta presentando cuando corrro el mapa pues me aparece el error ora-00001 violation unique constraint para ambos casos pk y el unique de los tres campos.  Para verificar este error he realizado una revision en los valores almacenados en la tabla_secuencia buscando si ya existen valores asignados en la tabla destino, pero en esta situación este no es el problema los valores de secuencia existentes en la tabla_secuencia no presentan conflicto. para la asignacion de los valores de secuencia se ha definido una funcion que me retorna el valor de secuencia correspondiente una vez este es asignado en la tabla destino mediante un trigger se elemina el valor de la tabla_secuencia.

  • Merge SQL

    En muchas ocasiones, especialmente en procesos ETL o de carga de datos para un data warehouse, por ejemplo, interesa hacer en una sola sentencia o en un solo paso la comprobación de si un registro existe, y si existe actualizarlo, y si no insertarlo. A esta combinación se le ha apodado UPSET, aunque en SQL existe una sentencia específica para hacerlo, que es MERGE.

  • Buenas tardes. Tengo un problema con una base de datos.

    Tengo estas 3 tablas:

 

 

 

Gestion del Conocimiento    |    Business Intelligence y Analítica    |     Bases de Datos    |      ERP     |      CRM      |     Tendencias tecnológicas