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).