| From: | "D(dot) Dante Lorenso" <dante(at)lorenso(dot)com> | 
|---|---|
| To: | Stephan Szabo <sszabo(at)megazone(dot)bigpanda(dot)com> | 
| Cc: | Martijn van Oosterhout <kleptog(at)svana(dot)org>, Bruno Wolff III <bruno(at)wolff(dot)to>, pgsql-general(at)postgresql(dot)org | 
| Subject: | Re: Delete all records NOT referenced by Foreign Keys | 
| Date: | 2003-12-14 09:02:49 | 
| Message-ID: | 3FDC2739.2040408@lorenso.com | 
| Views: | Whole Thread | Raw Message | Download mbox | Resend email | 
| Thread: | |
| Lists: | pgsql-general | 
Stephan Szabo wrote:
>On Sun, 14 Dec 2003, D. Dante Lorenso wrote:
>
>  
>
>>PG already can block a delete when it knows that foreign key exists, so
>>why can't I perform a query that says...
>>
>>    DELETE FROM tablename
>>    WHERE FOREIGN_KEY_EXISTS(oid) IS FALSE;
>>    
>>
>
>That's fairly different from the checks that are performed for the foreign
>keys which happen after the action has happened and errors to prevent the
>action from being visible.  The where clause happens long before that.  If
>the above has to check each referencing table for matching rows for each
>row in tablename, I'd also expect it to perform poorly.
>  
>
My hope was that there was some sort of (semaphore? / counter?) associated
with each row that indicated whether a dependency existed at all.  Although
that would most likely not be an indexed column, I could apply additional
WHERE constraints to avoid a full table scan.
If such a counter existed, it would certainly speed up deletes when no 
foreign
key checks were necessary.  But I suppose it would also slow down 
deletes when
it becomes necessary to decrement a counter for the dependencies created 
by the
row being deleted.
So...internally, how does a row KNOW that it can not be deleted because of
a foreign key constraint?  Whatever that mechanism is, isn't there a way for
me to make use of that as I try my query?
And... if not...how about something like this in PL/SQL:
    -- Find all the address records which might need to be removed...
    FOR my_rec IN
        SELECT addr_id
        FROM address
        WHERE acct_id = in_acct_id
        AND addr_is_active IS FALSE
    LOOP
        -- try to delete this record...
        DELETE FROM address
        WHERE addr_id = my_rec.addr_id;
END LOOP;
This will loop through the records one at a time and try to delete them.
However, I don't want to have any exceptions thrown if the DELETE action
can not be performed.  Is there a TRY/CATCH type of code that I can
surround the DELETE with to prevent the entire operation from being
aborted on the first error found?
Dante
----------
D. Dante Lorenso
dante(at)lorenso(dot)com
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Martijn van Oosterhout | 2003-12-14 09:34:18 | Re: Delete all records NOT referenced by Foreign Keys | 
| Previous Message | Greg Stark | 2003-12-14 08:53:26 | Re: Delete all records NOT referenced by Foreign Keys |