2017-02-14 1 views
-1

Je n'ai pas le code suivant:mise à jour DB2 en boucle n'exécute

BEGIN 
DECLARE cmd VARCHAR(1024); DECLARE attr CHAR(10); 
DECLARE attr2 CHAR(10); 
DECLARE at_end INTEGER DEFAULT 0; 
DECLARE not_found CONDITION FOR SQLSTATE '02000'; 
DECLARE updstr1 VARCHAR(1024); 
DECLARE updstr2 VARCHAR(1024); 


DECLARE c1 CURSOR FOR SELECT cmd, attr, attr2 
         FROM commandtbl2; 

DECLARE CONTINUE HANDLER FOR not_found SET at_end = 1; 

SET updstr1 = 'update commandtbl3 t2 set t2.XXXX = attr where t2.cmd=cmd'; 
SET updstr2 = 'update commandtbl3 t2 set t2.XXXX= attr2 where t2.cmd=cmd'; 
OPEN c1; 

ins_loop: LOOP 

    FETCH c1 INTO cmd, attr, attr2; 

    IF at_end = 1 THEN 
    LEAVE ins_loop; 
    ELSEIF cmd != '' THEN 
    ITERATE ins_loop; 
    END IF; 

    set updstr1= REPLACE(updstr1,'XXXX','attr'); 
    set updstr2= REPLACE(updstr2,'XXXX','attr2'); 

    EXECUTE IMMEDIATE updstr1; 
    EXECUTE IMMEDIATE updstr2; 


END LOOP; 

CLOSE c1; 
[email protected] 

Tout fonctionne sans erreur, mais quand je vérifie rien commandtbl3 réactualisé. Toutes les valeurs sont NULL mais doivent être remplacées. Il y a 7 lignes dans les deux tables et 5 ont des valeurs cmd correspondantes donc ces 5 lignes devraient être mises à jour.

Je ne suis pas sûr si le remplacement ne fonctionne pas ou l'exécution immédiate. Avec le débogage, j'ai découvert que les variables updstr1 et 2 sont vides après le remplacement ... mais pourquoi?

Pouvez-vous m'aider? Merci, TheVagabond

Comme demandé voici les définitions de commandtbl3 et 2:

CREATE TABLE "TEST"."COMMANDTBL3" (
    "ID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 NO CYCLE CACHE 2 NO ORDER), 
    "CMD" VARCHAR(1024 OCTETS) NOT NULL, 
    "ATTR" CHAR(10 OCTETS), 
    "ATTR2" CHAR(10 OCTETS), 
    CONSTRAINT "CC1455789123996" PRIMARY KEY 
    ("ID") 
) 

CREATE TABLE "TEST"."COMMANDTBL2" (
    "ID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 NO CYCLE CACHE 2 NO ORDER), 
    "CMD" VARCHAR(1024 OCTETS) NOT NULL, 
    "ATTR" CHAR(10 OCTETS), 
    "ATTR2" CHAR(10 OCTETS), 
    CONSTRAINT "CC1455789123996" PRIMARY KEY 
    ("ID") 
) 

COmmandtbl3 a CMD égale à commandtbl2 sauf pour les 2 lignes (7 lignes au total) et attr et attr2 sont NMULL dans commandtbl3 . Je veux que les valeurs de commandtbl2 attr et attr2 à écrire à commandtbl3 via la mise à jour avec un remplacement à la commande pour que je puisse avoir des espaces réservés XXXX

EST ICI LE CODE DE TRAVAIL:

Si quelqu'un a le même prob ici est le code de travail, même si changé de celui (en boucle maintenant, etc) à partir:

BEGIN 
DECLARE EOF INTEGER DEFAULT 0; 
DECLARE cmd VARCHAR(1024); DECLARE attr CHAR(10); 
DECLARE attr2 CHAR(10); 
DECLARE not_found CONDITION FOR SQLSTATE '02000'; 
DECLARE updstr1 VARCHAR(1024); 
DECLARE updstr2 VARCHAR(1024); 
DECLARE stmt1 STATEMENT; 
DECLARE stmt2 STATEMENT; 

DECLARE c1 CURSOR FOR SELECT cmd, attr, attr2 
        FROM commandtbl2 order by cmd; 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET EOF = 1; 

SET updstr1 = 'update commandtbl3 t2 set t2.XXXX = ? where t2.cmd= ?'; 
SET updstr2 = 'update commandtbl3 t2 set t2.XXXX= ? where t2.cmd= ?'; 
set updstr1= REPLACE(updstr1,'XXXX','attr'); 
set updstr2= REPLACE(updstr2,'XXXX','attr2'); 
insert into temptbl(text1,text2) values(updstr1,updstr2); 

prepare stmt1 from updstr1; 
prepare stmt2 from updstr2; 

OPEN c1; 


WHILE EOF = 0 DO 

FETCH from c1 INTO cmd, attr, attr2; 
EXECUTE stmt1 using attr, cmd; 
EXECUTE stmt2 using attr2, cmd; 

END WHILE; 

CLOSE c1; 
[email protected] 
+0

Vérifiez à nouveau le manuel sur l'utilisation des paramètres dans une instruction dynamique. Astuce: il y aurait une instruction 'PREPARE', et' EXECUTE' aurait une clause 'USING'. – mustaccio

+0

Je sais préparer une déclaration à partir d'autres langages de codage embarquant sql, en ai-je besoin lorsque je n'utilise que du SQL et que je n'ai pas de marqueur de paramètre? Je remplace juste une chaîne. – Thevagabond

+0

Vous vous attendez à ce que le dernier 'cmd' dans' où t2.cmd = cmd' soit remplacé par une variable que vous récupériez plus tôt, n'est-ce pas? Ça n'arrivera pas. – mustaccio

Répondre

1

Vous avez quelques erreurs logiques dans votre code.

  1. Dans votre boucle:

    IF at_end = 1 THEN 
        LEAVE ins_loop; 
    ELSEIF cmd != '' THEN 
        ITERATE ins_loop; 
    END IF; 
    

    La déclaration ELSEIF est dit DB2 que si cmd (de commandtbl2) est quelque chose mais une chaîne vide, il doit sauter les étapes restantes dans cette itération de la boucle (c'est-à-dire qu'il ne fera rien, et il suffit de revenir à l'instruction FETCH au début de la boucle).

    C'est probablement la raison pour laquelle vous ne voyez rien se produire. Comme @mustaccio mentionné dans les commentaires ci-dessus, il semble que vous supposiez que DB2 va remplacer par magie les variables avec leurs valeurs lorsque vous exécutez l'instruction EXECUTE IMMEDIATE. Votre déclaration:

    update commandtbl3 t2 set t2.XXXX = attr where t2.cmd=cmd 
    

    Votre code remplacera le XXXX, mais il vous semble comme vous en supposant que le = attr et =cmd seront également remplacés par les valeurs qui se fixent dans la déclaration FETCH. Ce n'est pas le cas.

    Voir cet exemple:

    DECLARE GLOBAL TEMPORARY TABLE t1 (c1 int) 
    ON COMMIT PRESERVE ROWS WITH REPLACE 
    @ 
    
    BEGIN 
        DECLARE v1 INT; 
        DECLARE vSQL VARCHAR(128); 
    
        SET vSQL = 'INSERT INTO SESSION.T1 values (v1)'; 
        SET v1 = 12; 
    
        EXECUTE IMMEDIATE vSQL; 
    END 
    @ 
    

    Lorsque la base de données atteint l'instruction EXECUTE IMMEDIATE, il ne remplacera pas v1 avec la valeur de v1 lors de l'exécution. Il va exécuter l'instruction exacte INSERT INTO SESSION.T1 values (v1). Cela échouera, bien sûr, car v1 ne signifie rien pour la base de données.

    Dans votre cas, les déclarations ne seront pas EXECUTE IMMEDIATEéchouent parce attr et cmd ne signifie quelque chose à la base de données - ils sont les noms de colonnes dans la table commandtbl3. Ainsi, vos déclarations de mise à jour seront exécutés (après la déclaration REPLACE):

    update commandtbl3 t2 set t2.attr = attr where t2.cmd=cmd 
    update commandtbl3 t2 set t2.attr2 = attr2 where t2.cmd=cmd 
    

    Ce sont essentiellement pas d'habitation - comme UPDATE T1 SET C1 = C1 WHERE C2 = C2.

    Ceci est un très bon exemple de pourquoi vous ne devriez pas déclarer des variables en utilisant les mêmes noms que les colonnes de votre base de données. Cela augmente la confusion et peut cacher les erreurs logiques.