> Hello 'stwizard',
> 
> Thursday, May 12, 2016, 12:46:25 AM, you wrote:
> 
>> Here is my simple Stored Procedure.  It simply looks for any
>> address in the ADDRESS table that starts with ‘0 ‘  as in “0 SE
>> ADAMS ST” and COUNT(*) how many time it might have been used in
>> PER_ADDRESS and if COUNT() > 0 delete the links from the PER_ADDRESS table.
> 
>>  
> 
>> The next line verifies that there is no remaining links in the
>> PER_ADDRESS table and then deletes the record from the ADDRESS table.
> 
>>  
> 
>> My problem is that even though ADDR_ID 347006 does not exist in the
>> PER_ADDRESS table, the “IF (NOT(EXISTS(SELECT 1..” line thinks there
>> is and skips the deletion of the record f  orm the ADDRESS table.  
> 
> 
>> What might I be doing wrong?
> 
> First of all, this is an executable SP, not intended to return a
> result set, so get rid of the RETURNS parameters and declare variables
> instead. While executable SPs *can* return a single-row result set,
> with your for-loop, the only result you would get back would be the
> values from the final iteration of the loop.  But that's not the
> reason for your unexpected results.
> 
> In your INTO clause, you are missing the colon (:) markers
> that are needed when variables or parameters are referred to in a DSQL
> statement.  I seem to recall that they are optional in v.2.5 (not
> sure) but that would not be a reason for me to omit them.
> 
> Your problem is your variables.  With both local variables and
> parameters that you are using like variables, you need to
> 
> (1) Initialise your variables before starting the loop (they start out
> as NULL)
> and
> (2) Re-initialise them at the end of the loop (otherwise, until the
> next time the loop gets a "hit", the variables retain the values that
> existed after the last "hit").
> 
> Also, once you fix those problems, I see no point in adding extra cost
> by revisiting the PER_ADDRESS table to verify the non-existence of
> the records you just deleted.  If the delete had failed, you would
> already be in an exception condition and would have jumped past that
> block to the last END statement.
> 
> You don't actually need ADDRESS1 in your working set, either, since
> you don't do anything with it.
> 
> With the correct initialisation/re-initialisation, you already have
> the value of ADDR_ID at that point:  either a genuine ID (if the
> current ADDRESS format matches the condition) or the dummy value from the
> initialisation (if no invalid addresses were found for that ADDR_ID in
> PER_ADDRESS).
> 
> CREATE PROCEDURE P_CLEAN_ADDR
> AS
>  DECLARE  ADDR_ID Integer = -1;
>  /* DECLARE ADDRESS VarChar(50) = ''; not needed */
>  DECLARE PER_ADDR_CNT SmallInt = -1;
> 
> begin
>  FOR SELECT A.ADDR_ID,
>             /* A.ADDRESS1, not needed */
>             (SELECT COUNT(*) FROM PER_ADDRESS PA
>              WHERE PA.ADDR_ID = A.ADDR_ID) AS PER_ADDR_CNT
> 
>         FROM ADDRESS A
>         WHERE ADDRESS1 STARTING WITH '0 '
>         INTO :ADDR_ID, /* :ADDRESS, */ :PER_ADDR_CNT
>       DO
>       BEGIN
>           IF (PER_ADDR_CNT > 0) THEN
>           begin
>             DELETE FROM PER_ADDRESS WHERE ADDR_ID = :ADDR_ID;
>             DELETE FROM ADDRESS WHERE ADDR_ID = :ADDR_ID;
>           end
>           -- re-initialise variables
>           ADDR_ID = -1;
>           /* ADDRESS = ''; */
>           PER_ADDR_CNT = -1;
>       END
> end ^^

Very exhaustive and a lot of useful advices ... ;-)

He also could simply have a cascading delete foreign key constraint on 
PER_ADDRESS referencing ADDRESS.



--
With regards,
Thomas Steinmaurer
http://www.upscene.com

Professional Tools and Services for Firebird
FB TraceManager, IB LogManager, Database Health Check, Tuning etc.
  • [firebird-su... 'stwizard' stwiz...@att.net [firebird-support]
    • Re: [fi... Helen Borrie hele...@iinet.net.au [firebird-support]
      • Re:... 'Thomas Steinmaurer' t...@iblogmanager.com [firebird-support]
        • ... 'stwizard' stwiz...@att.net [firebird-support]
      • RE:... 'stwizard' stwiz...@att.net [firebird-support]

Reply via email to