2010-09-02 5 views
0

J'ai une procédure, où je dois vérifier une certaine vue pour certaines entrées spécifiées et les supprimer en conséquence. Je l'ai utilisé l'approche suivante à cet effet -Postgresql: Comment rendre la requête suivante plus efficace

SELECT  id_1, 
      id_2, 
      id_3, 
      id_4 
INTO  v_id_1, 
      v_id_2, 
      v_id_3, 
      v_id_4 
FROM  v_doc 
WHERE  parent_id_1 = p_id_1 -- 'p_' suffix stands for function parameters 
      AND parent_id_2 = p_id_2 
      AND parent_id_3 = p_id_3 
LIMIT  1 
; 

WHILE v_id_1 IS NOT NULL 
LOOP 
    -- Code for child document line deletion goes here 


    SELECT  id_1, 
       id_2, 
       id_3, 
       id_4 
    INTO  v_id_1, 
       v_id_2, 
       v_id_3, 
       v_id_4 
    FROM  v_doc 
    WHERE  parent_id_1 = p_id_1 
       AND parent_id_2 = p_id_2 
       AND parent_id_3 = p_id_3 
    LIMIT  1 
    ; 
END LOOP; 

Est-ce est le moyen efficace, ou il est un moyen plus efficace de faire ce type de requête? Je parle de la façon dont je sélectionne les disques, bien sûr.

+0

@OMG: désolé, mon mauvais. Edited le code. Merci d'avoir signalé les erreurs. –

Répondre

3

Je pense que vous vous demandez comment vous pouvez supprimer chaque élément correspondant, si votre requête renvoie plusieurs lignes. Une plus rapide et le mode correcter est d'exécuter la requête une fois, et la boucle sur ses lignes:

DECLARE 
    r RECORD; 
BEGIN 
    FOR r IN SELECT id_1, id_2, id_3, id_4 
       FROM v_doc 
       WHERE id_1 = p_id_1 
       AND id_2 = p_id_2 
       AND id_3 = p_id_3 LOOP 
     -- delete item for r.id_1, r.id_2, etc. 
    END LOOP; 
END; 

Voir http://www.postgresql.org/docs/8.4/static/plpgsql-control-structures.html#PLPGSQL-RECORDS-ITERATING

une meilleure façon peut-être d'utiliser simplement une déclaration DELETE FROM x WHERE ..., si possible. Cela dépend de la simplicité de la suppression.

+0

Réponse élégante, +1. Cependant, je me retiens de choisir celui-ci comme réponse acceptée pour voir si d'autres moyens peuvent être trouvés. Merci. –

+1

L'utilisation d'une boucle lorsqu'une instruction SQL unique effectue le même travail est presque toujours le mauvais choix. Une base de données n'est pas destinée à traiter les données ligne par ligne, mais à traiter des ensembles de données. Optez pour l'instruction DELETE simple et votre performance sera bien meilleure –

+0

Je suis entièrement d'accord, c'est pourquoi j'ai mis cette dernière ligne là. Mais il n'était pas évident à 100% de la question qu'une seule instruction SQL * ferait * le même travail; dans tous les cas, si le demandeur est si novice dans les bases de données qu'il n'est pas familier avec l'astuce 'DELETE ... WHERE (query complexe) ', je ne vois aucun inconvénient à les déplacer progressivement. – Edmund

2

Y at-il quelque chose qui me manque sur l'utilisation:

DELETE FROM v_doc 
WHERE EXISTS(SELECT NULL 
       FROM v_doc x 
       WHERE x.id_1 = v_doc.id_1 
       AND x.id_2 = v_doc.id_2 
       AND x.id_3 = v_doc.id_3 
       AND x.id_4 = v_doc.id_4 
       AND x.parent_id_1 = p_id_1 
       AND x.parent_id_2 = p_id_2 
       AND x.parent_id_3 = p_id_3) 
Questions connexes