recherche

Maison  >  Questions et réponses  >  le corps du texte

L'exécution de l'instruction CONCAT dans une procédure stockée ne fonctionne pas

<p>J'ai deux tables, une table de base contenant diverses informations sur la valeur 'tconst' (également la clé primaire) et une autre table liée à plusieurs valeurs 'tconst' de 'nconst' sous le nom 'titleId' . </p> <p>---Table de base 'titlebasics'</p> <table class="s-table"> <tête> <tr> <th>tconst</th> <th>Type de titre</th> <th>...</th> ≪/tr> ≪/tête> <corps> <tr> <td>tt0000009</td> <td>Films</td> <td>...</td> ≪/tr> <tr> <td>tt0000147</td> <td>Films</td> <td>...</td> ≪/tr> <tr> <td>...</td> <td>...</td> <td>...</td> ≪/tr> </tcorps> </tableau> <p>---Tableau d'informations supplémentaires 'knownfortitles'</p> <table class="s-table"> <tête> <tr> <th>id</th> <th>ncconst</th> <th>Ordre des titres</th> <th>ID du titre</th> ≪/tr> ≪/tête> <corps> <tr> <td>1</td> <td>nm0000001</td> <td>1</td> <td>tt0050419</td> ≪/tr> <tr> <td>2</td> <td>nm0000001</td> <td>2</td> <td>tt0053137</td> ≪/tr> <tr> <td>...</td> <td>...</td> <td>...</td> <td>...</td> ≪/tr> </tcorps> </tableau> <p>Le "problème" est que certaines valeurs de <code>knownfortitles.titleId</code> n'existent pas dans <code>titlebasics.tconst</code>. Je souhaite créer une procédure stockée dans laquelle je peux passer en paramètres les noms de deux tables et de deux colonnes correspondantes. Ce processus vérifiera d'abord si la valeur qui n'existe pas dans la première table existe réellement dans la deuxième table et, si c'est le cas, ajoutera une nouvelle table à la deuxième table nommée <code>is_in_<base_table_name></code> . Il mettra ensuite à jour cette colonne avec la valeur booléenne de chaque ligne du deuxième tableau. Je souhaite faire cela dans une procédure stockée car j'ai beaucoup de tables avec ce problème et je veux pouvoir utiliser cette procédure au lieu d'écrire encore et encore le même code avec des valeurs différentes.Cependant, j'obtiens une erreur lorsque j'essaie d'appeler mon programme et je n'arrive pas à la corriger. </p> <p>En tant que procédure stockée, c'est là que je suis bloqué. </p> <pre class="brush:php;toolbar:false;">CRÉER UNE PROCÉDURE `CheckValueExistsInBaseTable`( DANS table vérifiée VARCHAR(100), DANS referencedBaseTable VARCHAR(100), DANS vérifiéCol VARCHAR(100), IN référencéCol VARCHAR(100) ) COMMENCER DECLARE new_column_name VARCHAR(100) DEFAULT 'is_in_baseTable'; DECLARE sql_statement1 VARCHAR(1000) DEFAULT 'SELECT NULL;'; DECLARE sql_statement2 VARCHAR(1000) DEFAULT 'SELECT NULL;'; SET @new_column_name = CONCAT('is_in_',referencedBaseTable); -- Ajouter une nouvelle colonne au tableau coché si elle n'existe pas SET @sql_statement1 = CONCAT('IF (SELECT CASE WHEN EXISTS( Choisir 1 FROM ', table vérifiée, ' OÙ ', col vérifié, ' PAS DANS (SELECT ', col référencé, ' FROM ', tableBase référencée, ')) PUIS 1 AUTRE 0 FIN ) = 1 ALORS ALTER TABLE ', vérifiéTable, ' ADD ', @new_column_name, ' BOOL; AUTRE SÉLECTIONNEZ NULL ; FIN SI'); PRÉPARER stmt1 FROM @sql_statement1 ; EXÉCUTER stmt1 ; DÉSALLOCATION PREPARE stmt1 ; -- Mettre à jour la colonne is_in_referencedBaseTable dans la table cochée SET @sql_statement2 = CONCAT('MISE À JOUR', table vérifiée, 'SET', @new_column_name, ' = CASE QUAND EXISTE (SELECT * FROM ', referencedBaseTable, ' OÙ ', referencedBaseTable, '.', referencedCol, ' = ', CheckTable, '.', CheckCol, ') THEN 1 ELSE 0 END'); PRÉPARER stmt2 FROM @sql_statement2 ; EXÉCUTER stmt2 ; DÉSALLOCATION PREPARE stmt2 ; FIN</pré> <p>Peu importe ce que j'essaie de modifier, cela me donne l'une des erreurs suivantes. </p> <blockquote> <p>Code d'erreur : 1064. Il y a une erreur dans votre syntaxe SQL ; consultez le manuel de la version de votre serveur MySQL pour connaître la syntaxe correcte à utiliser près de "NULL" à la ligne 1</p> </blockquote> <p> ou </p> <blockquote> <p>Code d'erreur : 1064. Il y a une erreur dans votre syntaxe SQL ; consultez le manuel de la version de votre serveur MySQL pour savoir comment utiliser 'IF (SELECT CASE WHEN EXISTS( Choisir 1 D'œuvres connues OÙ titleId NOT' sur la ligne 1</p> </blockquote> <p>J'ai également créé des programmes de test pour vérifier quelles pièces pourraient rencontrer des problèmes, mais les deux fonctionnent correctement, ce qui me rend encore plus confus. Le premier renvoie simplement ce que j'ai mis dans <code>CONCAT</code> pour voir s'il contient des erreurs de syntaxe.</p> <pre class="brush:php;toolbar:false;">CRÉER UNE PROCÉDURE `test`( DANS table vérifiée VARCHAR(100), DANS referencedBaseTable VARCHAR(100), DANS vérifiéCol VARCHAR(100), IN référencéCol VARCHAR(100), DANS new_column_name VARCHAR (100) ) COMMENCER -- Déclarer la variable et attribuer la valeur déclarer mavar VARCHAR(1000); DECLARE new_column_name VARCHAR(100) DEFAULT 'is_in_baseTable'; SET @new_column_name = CONCAT('is_in_',referencedBaseTable); SET mavar = CONCAT('IF (SELECT CASE WHEN EXISTS( Étape 1 FROM ', table vérifiée, ' OÙ ', col vérifié, ' PAS DANS (SELECT ', col référencé, ' FROM ', tableBase référencée, ')) PUIS 1 AUTRE 0 FIN ) = 1 ALORS ALTER TABLE ', vérifiéTable, ' ADD ', @new_column_name, ' BOOL; AUTRE SÉLECTIONNEZ NULL ; FIN SI'); -- Impression de la valeur sur la console SELECT concat(myvar) AS Variable ; FIN</pré> <p>此过程给出下一个结果:</p> <pre class="brush:php;toolbar:false;">IF (SELECT CASE WHEN EXISTS( Étape 1 来自知名作品 OÙ titleId NOT IN (SELECT tconst FROM titlebasics)) PUIS 1 AUTRE 0 FIN ) = 1 ALORS ALTER TABLE knownfortitles ADD is_in_titlebasics BOOL; AUTRE SÉLECTIONNEZ NULL ; FIN SI</pre> <p>确切的代码块。</p> <pre class="brush:php;toolbar:false;">CRÉER UNE PROCÉDURE `test2`() COMMENCER SI (SELECT CAS QUAND EXISTE ( Étape 1 来自知名作品 OÙ titleId NOT IN (SELECT tconst FROM titlebasics)) PUIS 1 AUTRE 0 FIN ) = 1 ALORS ALTER TABLE knownfortitles ADD is_in_titlebasics BOOL; AUTRE SÉLECTIONNEZ NULL ; FIN SI; FIN</pré> <p>此过程将列 <code>is_in_titlebasics</code> 添加到表 <code>knownfortitles</code> 中,这就是我想要发生的事情,所以这很好。此时,我完全迷失了,不知道为什么我的实际存储过程不起作用,因为它基本上是最后两个过程的组合。我暂时<code>CONCAT</code> 语句视为问题。</p> <p>
P粉644981029P粉644981029452 Il y a quelques jours605

répondre à tous(1)je répondrai

  • P粉798343415

    P粉7983434152023-09-07 00:02:02

    Grâce à P. Salmon, j'ai appris que le problème résidait dans l'exécution des IF ... THEN instructions à travers des instructions préparées. C'est impossible. Après quelques réflexions, j'ai trouvé le programme suivant, qui fonctionne exactement comme je le souhaite. J'espère pouvoir aider certaines personnes qui ont des problèmes similaires aux miens.

    DELIMITER $$
    USE `<schema>`$$
    CREATE DEFINER=`Setupinfolab`@`%` PROCEDURE `CheckValueExistsInBaseTable`(
        IN checkedTable VARCHAR(100),
        IN referencedBaseTable VARCHAR(100),
        IN checkedCol VARCHAR(100),
        IN referencedCol VARCHAR(100)
        )
    BEGIN
        SET @checkedTable = checkedTable;
        SET @referencedBaseTable = referencedBaseTable;
        SET @checkedCol = checkedCol;
        SET @referencedCol = referencedCol;
        SET @new_column_name  = CONCAT('is_in_', referencedBaseTable);
        
        -- Check if there are indeed values in checkedCol that are not present in referencedCol
        SET @query1 = CONCAT('
            SELECT CASE WHEN EXISTS(
                SELECT 1 
                FROM ',@checkedTable,'
                WHERE ',@checkedCol,' NOT IN (SELECT ',@referencedCol,' FROM ',@referencedBaseTable,')) 
                THEN 1 ELSE 0 END 
                INTO @proceed');
            
        -- Adding the boolean column
        SET @query2 = CONCAT('
            ALTER TABLE ',@checkedTable,' ADD ',@new_column_name,' BOOL;');
        
        -- Inserting boolean values in new column according to presence in referencedCol
        SET @query3 = CONCAT('
            UPDATE ',@checkedTable,' SET ',@new_column_name,' = (
                CASE WHEN EXISTS(
                    SELECT * 
                    FROM ',@referencedBaseTable,' 
                    WHERE ',@referencedBaseTable,'.',@referencedCol,' = ',@checkedTable,'.',@checkedCol,')
                THEN true ELSE false END
                ) WHERE id<>0;');
        
        PREPARE stmt1 FROM @query1;
        EXECUTE stmt1;
        
        IF @proceed = 1
        THEN 
            PREPARE stmt2 FROM @query2;
            EXECUTE stmt2;
            PREPARE stmt3 FROM @query3;
            EXECUTE stmt3;
            SELECT CONCAT(@new_column_name,' column added to table ', @checkedTable,'.') 
                AS 'Message: Done';
            DEALLOCATE PREPARE stmt2;
            DEALLOCATE PREPARE stmt3;
        ELSE 
            SELECT 'All values are present in base table. Adding column is thus unnecessary.' 
                AS 'Message: UNNECESSARY';
        END IF;
        
        DEALLOCATE PREPARE stmt1;
    END$$
    DELIMITER ;
    ;

    Cependant, je tiens à souligner que je n'ai pas ajouté TRY ... CATCH ou quoi que ce soit pour empêcher le programme de générer une erreur. Ce n’est que le strict minimum pour que cela fonctionne.

    Processus d'appel

    CALL CheckValueExistsInBaseTable(
        'knownfortitles',
        'titlebasics',
        'titleId',
        'tconst'
        );

    Confirmation du message de retour :

    ou message d'avertissement :

    Seulement dans le premier cas, les colonnes TINYINT(1) seront ajoutées selon les besoins.

    répondre
    0
  • Annulerrépondre