tags:

views:

56

answers:

2

I have a procedure, where I have to check a certain view for some specified entries and delete them accordingly. I have used the following approach for this purpose -

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;

Is this is the efficient way, or there is a more efficient way to do this type of query? I am talking about the way I am selecting the records, of course.

+3  A: 

Hi, I think you're wondering how you can delete each matching item, if your query returns many rows. A quicker and correcter way is to run the query once, and loop over its rows:

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;

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

An even better way might be to simply use a DELETE FROM x WHERE ... statement, if possible. It depends how simple the deletion is.

Edmund
Elegant answer, +1. However, I am holding out myself from selecting this one as accepted answer to see if any other ways can be found. Thanks.
Night Shade
Using a loop when a single SQL statement would do the same job is almost always the wrong choice. A database is not meant to deal with the data row by row, but to deal with sets of data. Go for the single DELETE statement and your performance will be a lot better
a_horse_with_no_name
I agree wholeheartedly, which is why I put that last line there. But it was not 100% obvious from the question that a single SQL statement *would* do the same job; in any case, if the asker is so new to DBs that they're not familiar with the `DELETE ... WHERE (complex query)` trick, I see no harm in moving them towards it gradually.
Edmund
+2  A: 

Is there something I miss about using:

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)
OMG Ponies