2012-07-27 13 views
6

Actualmente estoy escribiendo instrucciones de actualización para mantener constantemente actualizada una tabla que puede consultarse. El esquema es idéntico entre ambas tablas y los contenidos no son importantes:Actualización de Oracle SQL basada en la subconsulta entre dos tablas

STAGING 

ID 
NAME 
COUNT  

PRODUCTION 

ID 
NAME 
COUNT 

Mi instrucción de actualización se ve de la siguiente manera:

update PRODUCTION 
set name = (select stage.name from staging stage where stage.name=name and rownum <2), 
    count = (select stage.countfrom staging stage where stage.count=count and rownum <2); 

Las dos cosas a destacar es que 1) No hay donde cláusula el final de mi actualización (este puede ser el problema) y 2) todos los registros después de ser actualizados tienen los mismos valores. Lo que quiero decir con esto es la siguiente:

BEFORE UPDATE: 

1,"JOHN", 12; 
2,"STEVE",15; 
3,"BETTY",2; 

AFTER UPDATE 

    1,"JOHN", 12; 
    2,"JOHN",12; 
    3,"JOHN",12; 

Mi pregunta es ¿cómo puedo solucionar esto para que el cuadro refleja adecuadamente "nuevos" datos de puesta en escena como una actualización de SQL correcta?

ACTUALIZACIÓN

Así que mis datos de estadificación podrían casualmente reflejan lo que está en PRODUCTION y por el bien de la discusión se hará lo siguiente:

STAGING DATA TO MERGE: 

    1,"JOHN", 12; 
    2,"STEVE",15; 
    3,"BETTY",2; 

ACTUALIZACIÓN el segundo

La consulta que Me gustaría ejecutar sería esto:

update PRODUCTION 
set production.name = staging.name, 
    production.count = staging.count 

where production.name = staging.name; 

Sin embargo, esto da lugar a problemas de identificadores válidos en "staging.name"

+0

¿Desea mantener ** tabla ** ** y ** contar ** en ** tabla ** PRODUCCIÓN ** actualizada y ** tabla ** ESTÁNDAR ** está cambiando? – hmmftg

+0

¿Por qué no usa desencadenantes para insertar nuevos valores en lugar de esta actualización? ¿Qué hace exactamente esta actualización? – hmmftg

+0

De acuerdo, al sincronizar tablas, los activadores pueden ser realmente útiles para mantenerlos actualizados en tiempo real. Solo tenga cuidado con la mutación de errores de tabla, y asegúrese de hacerlo como DESPUÉS DE INSERTAR O ACTUALIZAR. – Hermit

Respuesta

26

Hay dos maneras de hacer lo que está tratando

Uno es un Multi-column Correlated Update

UPDATE PRODUCTION a 
SET (name, count) = (
    SELECT name, count 
    FROM STAGING b 
    WHERE a.ID = b.ID); 

DEMO

Usted puede utilizar merge

MERGE INTO PRODUCTION a 
USING (select id, name, count 
      from STAGING) b 
ON (a.id = b.id) 
WHEN MATCHED THEN 
UPDATE SET a.name = b.name, 
      a.count = b.count 

DEMO

+0

Déjenme probar la correlación de varias columnas. Tuve que alejarme de la fusión debido a que es lenta (más de 10 millones de registros) – Woot4Moo

0

Como se ha notado, que no tienen la selectividad a la instrucción de actualización por lo que es la actualización de la tabla completa. Si desea actualizar filas específicas (es decir, donde coinciden los ID), probablemente desee hacer una subconsulta coordinada.

Sin embargo, dado que está utilizando Oracle, podría ser más fácil crear una vista materializada para su tabla de consulta y permitir que el mecanismo de transacción de Oracle maneje los detalles. Los MV funcionan exactamente como una tabla para consultar la semántica, son bastante fáciles de configurar y le permiten especificar el intervalo de actualización.

1

Sin ejemplos del conjunto de datos de puesta en escena, este es un plano en la oscuridad, pero ¿ha intentado algo como esto?

update PRODUCTION p, 
     staging s 
set p.name = s.name 
    p.count = s.count 
where p.id = s.id 

Esto funcionaría suponiendo que la columna de id coincida en ambas tablas.

+0

¿Qué ocurre si las únicas cosas con las que quiero hacer coincidir son las cláusulas where de mis subconsultas? IE establece blah donde p.name = s.name y p.count = s.count? – Woot4Moo

+0

Si lo hiciera, establecería a = to b donde a es = to b (es decir, no haría nada). – Hermit

+0

Oops falló la lógica de mi parte :) – Woot4Moo

0

Pruébalo ..
PRODUCCIÓN actualizar un
SET (nombre, count) = (
nombre SELECT, cuentan
DE ESTADIFICACIÓN b
DONDE a.ID = b.ID)
DONDE EXISTE (SELECCIONAR 1
DE ESTADIFICACIÓN b
WHERE a.ID = b.ID
);

Cuestiones relacionadas