web-dev-qa-db-fra.com

PL / SQL Insertion d'une ligne pour chaque résultat dans une sélection

J'écris une procédure PL/SQL qui effectue une sélection basée sur des variables d'entrée, puis insère une ligne pour chaque résultat dans la sélection. J'ai du mal à déboguer ce qui ne va pas avec ma requête en raison de ma nouveauté en PL/SQL. Je sais que cela doit être facile, mais je suis coincé ici pour une raison quelconque. Merci de votre aide!

CREATE OR REPLACE PROCEDURE setup_name_map(ranking_id IN NUMBER, class_string IN VARCHAR2) 
IS
BEGIN

    FOR rec IN (SELECT NAME_ID FROM PRODUCT_NAMES WHERE NAME = class_string)
    LOOP
        EXECUTE IMMEDIATE 'INSERT INTO NAME_RANKING (NAME_ID, RANKING_ID) VALUES (' || rec.NAME_ID || ', ' || ranking_id || ')';
    END LOOP;
END;

Selon Oracle Developer Compiler ... 'NAME_ID' est un identifiant non valide. J'ai essayé de le mettre entre guillemets mais pas de dés. Il se plaint également que l'utilisation des variables d'index de boucle 'REC' n'est pas valide. Toute aide est très appréciée.

18
Craig

Il n'y a pas besoin de SQL dynamique ici:

BEGIN

    FOR rec IN (SELECT NAME_ID FROM PRODUCT_NAMES
                WHERE NAME = class_string)
    LOOP
        INSERT INTO NAME_RANKING (NAME_ID, RANKING_ID)
        VALUES (rec.NAME_ID, ranking_id);
    END LOOP;
END;

Mieux encore, vous pouvez éviter une approche lente du curseur ligne par ligne comme ceci:

BEGIN
    INSERT INTO NAME_RANKING (NAME_ID, RANKING_ID)
    SELECT NAME_ID, ranking_id FROM PRODUCT_NAMES
    WHERE NAME = class_string;
END;

Si vous aviez vraiment besoin du SQL dynamique, vous ne devriez pas y concaténer de valeurs, mais utiliser des variables de liaison:

BEGIN

    FOR rec IN (SELECT NAME_ID FROM PRODUCT_NAMES
                WHERE NAME = class_string)
    LOOP
        EXECUTE IMMEDIATE 'INSERT INTO NAME_RANKING 
                           (NAME_ID, RANKING_ID) VALUES (:b1, :b2)
        USING rec.NAME_ID, ranking_id;
    END LOOP;
END;
48
Tony Andrews