jueves, 2 de abril de 2009

Update de tablas con inner join

Normalmente las consultas de update que contienen inner dan alguno de los siguientes errores:
SQL Error: ORA-00933: comando SQL no terminado correctamente
ORA-00933: SQL command not properly ended

Una opción es convertir estas sentencias en otras.

Ejemplo de consulta de update con inner que NO funciona:
UPDATE tabla1
SET columna1 = tabla2.columna1
from tabla1 INNER JOIN tabla2
ON (tabla1.columna2 = tabla2.columna2) AND (tabla1.columna3 = tabla2.columna3)


Ejemplo de consulta que ha sido transformada:

UPDATE tabla1
SET columna1 = (
select tabla2.columna1 from tabla2
WHERE (tabla1.columna2 = tabla2.columna2) AND (tabla1.columna3 = tabla2.columna3)
)


En realidad la hemos convertido en una subselección o un filtro. El problema está en que se va a realizar la consulta de select por cada una de las filas de la tabla. Esta consulta sólo es util para tablas que no tienen excesivas filas

Si necesariamente necesitamos realizar el update de la tabla mediante el join la sintaxis ha de ser la siguiente:

UPDATE
(select
tabla1.columna1 old_valor ,
tabla2.columna2 new_valor
from tabla1 INNER JOIN tabla2
ON (tabla1.columna4 = tabla2.columna4) AND (tabla1.columna3 = tabla2.columna3))
SET old_valor = new_valor

Para que esto pueda realizarse las dos tablas que participan en el inner tienen que tener la constaint unique o primary key:
alter table tabla1 add constraint tabla1_u unique (columna4,columna3);

En el caso de no tenerla podríamos forzar la sentencia con el hint /*+BYPASS_UJVC*/ .

Para poder usar la sentencia SET, forzosamente tendremos que dale nombre a las columnas implicadas (en este caso con los nombres old_valor y new valor), ya que no podemos usar los nombres de las tablas (no podemos usar tabla2.columna2 como valor asignado).

4 comentarios:

Julius Vega dijo...

Excelente el Hint /*+BYPASS_UJVC*/ lo probe y funciona super bien; me permitio actualizar mi tabla sin problema con todo y Joins. Muchas gracias por este post.

Crashmetal dijo...

Hola dieguz2, esta muy bueno tu ejemplo, Gracias!! aiii dejo mi granito de arena. Saludos

UPDATE tb1
(select
tb1.columna1 old_valor ,
tb2.columna2 new_valor
FROM tabla1 tb1
INNER JOIN tabla2 tb2
ON (tb2.columna4 = tb1.columna4) AND tb2.columna3 IS NOT NULL
)
SET tb1.old_valor = tb2.new_valor

Aitor Aznar dijo...

A mí también me ha servido, muchas gracias

Hernaldo Gonzalez dijo...

Excelente, preciso, gracias