UPDATE sql avec calcul de la valeur à modifier

UPDATE sql avec calcul de la valeur à modifier - SQL/NoSQL - Programmation

Marsh Posté le 25-03-2019 à 11:51:00    

Bonjour,
 
Je souhaite dans une table Oracle, modifier une valeur, en la calculant de la ligne suivante afin d'éviter les ruptures.
Cette table contient une zone DEB qui contient la valeur de début et une zone FIN qui contient la valeur de fin de la série.
Nous ne devons pas avoir de vide dans notre série, de ce fait je dois modifier la valeur fin avec la valeur DEB -1 de la ligne suivante.
 
J'ai essayé la commande LEAD, mais celle ci fonctionne très bien avec un sélect mais ne fonctionne pas avec un update.
Ma table fait plusieurs milliers de lignes
Table RANG de n colonnes avec 2 colonnes DEB et FIN, il n'y pas de doublon dans ces items.
 
- SELECT deb , fin , to_char(to_number(LEAD(deb,1) OVER (ORDER BY deb , fin) - 1 )) NVX_FIN FROM rang ;
 
DEB (CHAR)           FIN (CHAR)           FIN (après update)
0000000000000000001  0000000000000000999  0000000000000002000 (0000000000000002001 - 1)  
0000000000000002001  0000000000000040999  0000000000000040999 (ligne inchangée 0000000000000041000 - 1)
0000000000000041000  0000000000000049999  0000000000000069999 (0000000000000070000 - 1)  
0000000000000070000  0000000000000999999  0000000000000999999  dernière ligne donc inchangée  
 
j'ai essayé  
- UPDATE rang SET fin = to_char(to_number(LEAD(deb,1) OVER (ORDER BY deb , fin) - 1 )) where fin < MAX(fin) ;
  ERROR ORA-30483: window  functions are not allowed here
- UPDATE rang SET fin = cast(lead(deb,1) over (order by deb , fin) as decimal)+1 where rownum < 4 ;
  ERROR ORA-30483: window  functions are not allowed here
- UPDATE rang SET fin = (lead(deb,1) over (order by deb , fin) +1) where rownum < 4 ;
  ERROR ORA-30483: window  functions are not allowed here
 
- UPDATE rang SET A fin = (SELECT to_char(to_number(LEAD(A.deb,1) OVER (ORDER BY B.deb , B.fin) - 1 )) from rang B where A.deb = B.deb ) where A.deb in ( '0000000000000000001' , '0000000000000002001 ' ) ;
équivalemment à
  UPDATE rang SET A fin = (SELECT to_char(to_number(LEAD(B.deb,1) OVER (ORDER BY B.deb , B.fin) - 1 )) from rang B where A.deb = B.deb ) where A.deb in  ( '0000000000000000001' , '0000000000000002001 ' ) ;
=> update  réalisés avec fin toujours à 'null' au lieu de la valeur calculée dans le LEAD.
 
Avez vous une idée pour réussir mon update avec une autre commande que LEAD ou une meilleure utilisation ?
 
Par avance, merci

Reply

Marsh Posté le 25-03-2019 à 11:51:00   

Reply

Marsh Posté le 30-03-2019 à 10:16:16    

Par hasard, dans ta table, tu n'aurais pas un id allant de 1 à n (sans trous) ou un champ "rang" qui permet de numéroter tes lignes dans la BD. Si c'est pas le cas, ça serait possible de rajouter ce champ ? Ca pourrait même être une sorte de variable temporaire si Oracle supporte de truc là.
Parce que mon idée, c'est de faire :
Update Rang A Set A.Fin = (select B.Fin from Rang B Where B.numligne = A.numligne+1) - 1
 
PS : j'ai jamais fait d'Oracle, que du Mysql et du MSSql. Mais tu comprends l'idée ?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 31-03-2019 à 08:49:00    

Perso je ferais comme ça,

 

1 vue sur la table ordonnée avec un rownum
1 autre vue sur la même table ordonnée avec un rownum

 

J'utilise un create table as select pour créer la table qui t'intéresse. Dans le select je fais une jointure avec view1.rownum = view2.rownum et je conserve les valeurs des colonnes qui m'intéresse à savoir pour une ligne donnée view1.deb et view2.deb - 1

 

Les vues peuvent être des inline views

 

Va y avoir un problème avec la dernière ligne, peut êre un left outer join pourrait régler le problème, ou un insert à la fin pour cette ligne

 

L'ancienne table est renommé table_old, la nouvelle table est renommée avec le nom de l'ancienne table

 

À tester parceque ça fait 3 ans que je fais plus d'oracle.


Message édité par exhortae le 31-03-2019 à 08:49:54
Reply

Marsh Posté le 31-03-2019 à 13:32:45    

Pourquoi as-tu besoin de 2 vues identiques ? Une seule suffit.
Une requête comme ça, ça le fait pas ?
Update Rang A Set A.Fin = (select B.Fin from Rang B Where B.rownum= A.rownum+1) - 1  
 
Effectivement, faudra traiter avec une autre requête la dernière ligne.
 
Edit : n'étant pas familié d'Oracle, je te laisse le soin d'utiliser les bonnes fonctions pour effectuer l'opération sur la chaîne de caractère d'extract de la valeur à laquelle on fait -1.


Message édité par rufo le 31-03-2019 à 13:33:39

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed