0
votes

Utiliser d'abord chercher une expression de cas

db2 udb v11.x.

est-il possible d'utiliser Fetch d'abord dans une requête de mise à jour qui utilise un cas? Je comprends une sorte de comprendre pourquoi cela ne fonctionne pas mais je me demandais s'il y avait un moyen. Par exemple: P>

SQL0811N  The result of a scalar fullselect, SELECT INTO statement, or VALUES
INTO statement is more than one row


2 commentaires

Quel est le but que vous essayez d'atteindre? Avez-vous peur, qu'une seule instruction mise à jour mène à la journalisation de la condition complète?


Les objectifs sont 1) Mise à jour tandis que vous devez extraire des lots plus petits pour empêcher le verrouillage 2) Mise à jour rapidement - avoir à exécuter deux requêtes différentes sur une table de millions de lignes prendrait de longue durée.


3 Réponses :


0
votes

Veuillez utiliser la clause lors de la gestion de la sous-requête, vous pouvez avoir plusieurs valeurs dans l'autre table,

"UPDATE mytable SET cstate = CASE WHEN cstate in (SELECT cstate FROM mytable WHERE cstate = 801 FETCH FIRST 20000 ROWS ONLY) THEN cstate = 1 AND rstate = 1 WHEN cstate in (SELECT cstate FROM mytable WHERE cstate = 804 FETCH FIRST 20000 ROWS ONLY) THEN cstate = 4 AND rstate = 4 END"


4 commentaires

Bonjour, merci pour la réponse rapide. J'ai essayé l'erreur et j'ai reçu l'erreur suivante: SQL0582N Une expression de cas dans une clause de valeurs, dans le prédicat, le groupe par clause ou l'ordre par clause ne peut pas inclure d'un prédicat quantifié, un prédicat en utilisant un prédicat complet ou un prédicat existant


Je fixe deux colonnes, y compris le cstate en fonction de ce que le cstate est réglé sur. J'aime chercher x rangées à la fois pour le faire (dans une boucle) car j'aurai potentiellement des millions à faire. Je pouvais simplement diviser cela en deux questions, mais je voulais éviter de traverser la table deux fois.


La requête ne fonctionnera pas de cette façon, vous devez réécrire la requête


Fournir vos données d'échantillonnage et résultat souhaité, avoir une sous-requête sans jointure ne fonctionnera pas



1
votes

Ce serait la méthode la plus simple xxx

il suffit de continuer à l'exécuter jusqu'à ce qu'elle met à jour aucune ligne de lignes.


4 commentaires

Merci Paul. Cela ne fonctionne pas si ... Obtenir une affectation: SQL0407N affectation d'une valeur null à une colonne NON NULL "TBSPaceid = 6, tableID = 5, colno = 24" n'est pas autorisé. Sqlstate = 23502 Colno est la colonne CSTATE. J'ai essayé de modifier un peu la requête, mais je ne pouvais pas le faire fonctionner. Il faut également ajouter la possibilité de modifier la deuxième rstate de la colonne ... je ne suis pas claire sur le point de savoir s'il est mis à jour par déclaration de cas ou s'il n'est pas mis à jour uniquement en dehors de la sous-requête, qui semble vaincre le but de ce que dans la déclaration de cas. ?


@Nonasbuzines L'expression case lorsque cstate = 801 puis cstate = 1 et rstate = 1 quand ... fin retourne la valeur booléenne. Je ne pense pas que c'est vraiment ce que vous voulez - mettre à jour 2 colonnes int.


Ok, je n'avais pas examiné cela étroitement à la déclaration de cas. Je vais mettre à jour ma réponse afin que cela rend un peu plus de sens


Je n'étais pas au courant que DB2 prise en charge est distinct de . Merci



0
votes

Vous pouvez essayer positionné la mise à jour code> avec comme commits après N telles mises à jour.

--#SET TERMINATOR @
BEGIN
  DECLARE V_BATCH_COUNT INT DEFAULT 0;

  FOR V AS C1 CURSOR WITH HOLD FOR
    SELECT 1 DUMMY FROM mytable FOR UPDATE OF cstate, rstate
  DO
    UPDATE mytable
    SET 
      cstate = ...
    , rstate = ...
    WHERE CURRENT OF C1;

    SET V_BATCH_COUNT = V_BATCH_COUNT + 1;
    IF V_BATCH_COUNT = 20000 THEN 
      COMMIT;
      SET V_BATCH_COUNT = 0;
    END IF;
  END FOR;
  IF V_BATCH_COUNT <> 0 THEN
    COMMIT;
  END IF;
END
@


1 commentaires

Ooow ... curseurs. Je n'ai pas travaillé avec des curseurs pendant une longue période et c'était en code C. Comme vous le dites, super lent. J'écris dans le script Shell pour cela, cela serait donc plus rapide si je déverrouis les résultats dans une table Temp ou un fichier, puis traité dans de petits lots. Je cherchais juste une balle d'argent que je pourrais manquer, mais merci pour l'aide.