web-dev-qa-db-fra.com

Mise à jour Oracle SQL basée sur une sous-requête entre deux tables

J'écris actuellement des instructions de mise à jour afin de maintenir une table interrogeable constamment à jour. Le schéma est identique entre les deux tables et le contenu n'est pas important: 

STAGING  

ID  
NAME  
COUNT    

PRODUCTION  

ID  
NAME  
COUNT

Ma déclaration de mise à jour se présente comme suit: 

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

Les deux choses à noter sont que 1) Il n'y a pas de clause where à la fin de ma mise à jour (cela peut être le problème) et 2) tous les enregistrements après avoir été mis à jour ont les mêmes valeurs. Ce que je veux dire par ceci est le suivant: 

BEFORE UPDATE:  

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

AFTER UPDATE  

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

Ma question est la suivante: comment puis-je résoudre ce problème de sorte que le tableau reflète correctement les "nouvelles" données issues du stockage intermédiaire en tant que mise à jour SQL correcte?

METTRE &AGRAVE; JOUR 

Ainsi, mes données de transfert pourraient coïncider par hasard ce qui est dans PRODUCTION et aux fins de la discussion, elles: 

STAGING DATA TO MERGE:  

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

METTRE À JOUR le second  

La requête que je voudrais lancer serait la suivante: 

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

where production.name = staging.name;

Cela entraîne toutefois des problèmes d'identifiant non valides sur "staging.name"

9
Woot4Moo

Il y a deux façons de faire ce que vous essayez

One is a Mise à jour corrélée multi-colonnes

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

DEMO

Vous pouvez utiliser 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

32
Conrad Frix

Sans des exemples de l'ensemble de données sur la mise en scène, c'est un coup dans le noir, mais avez-vous déjà essayé quelque chose comme ça?

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

Cela fonctionnerait en supposant que la colonne id corresponde aux deux tables.

1
Hermit

Essayez-le .. 

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

Comme vous l'avez remarqué, votre déclaration de mise à jour n'est pas sélective, elle met donc à jour tout votre tableau. Si vous souhaitez mettre à jour des lignes spécifiques (c'est-à-dire où les ID correspondent), vous souhaiterez probablement effectuer une sous-requête coordonnée.

Cependant, puisque vous utilisez Oracle, il pourrait être plus facile de créer une vue matérialisée pour votre table de requêtes et de laisser le mécanisme de transaction d'Oracle gérer les détails. Les MV fonctionnent exactement comme une table pour interroger la sémantique, sont assez faciles à configurer et vous permettent de spécifier l’intervalle de rafraîchissement.

0
khoxsey