Erreur sur variable à l'exécution d'une procédure
Bonjour à tous,
Ça fait très longtemps que je n'ai pas fait de PL-SQL et c'est la 1ère fois sous MySQL, j'avoue être plus que rouillé ...
Bref,
J'ai voulu créer une procédure me permettant de voir la fiabilité des données que l'on doit importer notamment en obtenant le pourcentage de champ vide.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| DELIMITER |
CREATE PROCEDURE `proc_champ_NULL` (IN `vi_nomtable` VARCHAR(30) charset utf8)
BEGIN
DECLARE `v_finished` INT DEFAULT 0;
DECLARE `c_nomcol` VARCHAR(40);
DECLARE `v_nbligne` INT DEFAULT 0;
DECLARE `v_result` INT DEFAULT 0;
DECLARE `v_dt_chargement` DATE;
DECLARE done INT DEFAULT 0;
DECLARE `cur_nom_table` CURSOR FOR
SELECT `column_name` FROM information_schema.columns WHERE table_name = `vi_nomtable`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
SELECT '1';
SELECT CURRENT_TIMESTAMP INTO `v_dt_chargement`;
SELECT '2';
CREATE TABLE IF NOT EXISTS `stat_champ_NULL`
(
`nom_table` VARCHAR(30) NULL,
`nom_col` VARCHAR(40) NULL,
`taux_NULL` VARCHAR(4) NULL,
`nb_ligne_total` VARCHAR(4) NULL,
`dt_chargement` DATE NULL
)
ENGINE = InnoDB;
SELECT '3';
OPEN `cur_nom_table`;
SELECT '4';
SELECT COUNT(*) INTO `v_nbligne` FROM `vi_nomtable`;
SELECT '5';
REPEAT
FETCH `cur_nom_table` INTO `c_nomcol`;
SELECT '6';
SELECT SUM(CASE WHEN `c_nomcol`='' THEN 1 ELSE 0 END)*100/`v_nbligne`
INTO `v_result`
FROM `vi_nomtable`;
SELECT '7';
INSERT INTO `stat_champ_NULL`
VALUES (
`vi_nomtable`,
`c_nomcol`,
`v_result`,
`v_nbligne`,
`v_dt_chargement`
)
;
SELECT '8';
UNTIL done END REPEAT;
CLOSE `cur_nom_table`;
SELECT '9';
END|
DELIMITER ; |
Et quand je l'execute,
Code:
CALL proc_champ_null('import_ldapuser');
voici ce que j'ai en retour :
Citation:
Error Code: 1146 Table 'dbappstore.vi_nomtable' doesn't exist
J'ai mis des "select +num" un peu partout pour savoir ou ça plante.
(J'ai pas trouvé d'autre méthode pour m'aider au débugage)
C'est ligne 36 :
Code:
SELECT COUNT(*) INTO `v_nbligne` FROM `vi_nomtable`;
Visiblement il prend pour valeur le nom de la variable "vi_nomtable" et non sa valeur.
J'ai essayé quantité de solution sans succès ...
Donc c'est ici, l’âme en peine que j’espère trouver un peu de réconfort.
Merci pour toute l'aide que vous pourrez m'apporter.
(ou bien même un peu de réconfort ;))
c'est ok ... je vais tacher de creuser
Merci jowo,
Tu m'a fait découvrir les requete préparée Execute et ça ma bien comme ça.
Il me reste à comprendre :
1) pourquoi j'ai du préfixer la variable avec @ (ça ne marchait pas tel que tu me le proposais)
Code:
1 2
| SET @ddl = CONCAT('ALTER TABLE `test`.`tblTmpImportCsv` ADD ', NomCol, ' varchar(300)') ;
PREPARE stmt FROM @ddl; |
2) pourquoi je n'arrive pas à utiliser le vrai coté dynamique des requêtes préparée (préparer une seul fois avant la boucle pour ne faire que l'appel à chaque changement de valeur de la variable)
J'essaye ça mais ça ne marche pas
Code:
1 2 3 4 5 6 7 8
|
PREPARE stmt from 'Alter Table `test`.`tblTmpImportCsv` ADD ? varchar(300) ; ';
WHILE CountCol < iNbCol DO
set CountCol = CountCol + 1;
set @NomCol = concat('Col', CountCol);
Execute stmt using @NomCol ;
END WHILE;
DEALLOCATE PREPARE stmt; |
Si je trouve (avant que qq'un ne m'explique) je posterai là l'explication
A+
Merci pour vos explications
Bonjour,
Merci à tous les 2 pour ces explications détaillées.
- Jowo, j'ai suivi le conseil et ma boucle ne prépare plus que la requete, qui est executée en une seule passe à la sortie.
Code:
1 2 3 4 5 6 7 8 9 10
| set @ddl = 'CREATE TABLE `tblTmpImportCsv` (' ;
WHILE CountCol < iNbCol DO
set @ddl = concat(@ddl, 'Col', CountCol, ' varchar(300), ');
set CountCol = CountCol + 1;
END WHILE;
set @ddl = concat(@ddl, 'Col', CountCol, ' varchar(300)) ');
PREPARE stmt from @ddl;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt; |
- Punkoff, j'ai bien noté qu'une bonne modélisation n'a pas besoin d'être changée dynamiquement. En l’occurrence, il ne s'agit pas vraiment d'une appli, je me fait juste une petite proc stock réutilisable car j'ai souvent besoin de charger en base des fichiers plats volumineux de tout genre.
(il me reste à broder un peu pour ajouter le "load data infile", qq paramêtres, etc)
Merci