Domanda

Ho la seguente procedura:

CREATE PROCEDURE foo ()
    SELECT * FROM fooBar INTO TEMP tempTable;

    -- do something with tempTable here

    DROP TABLE tempTable;
END PROCEDURE;

Che cosa succede se c'è un'eccezione prima che il DROP TABLE si chiama? Sarà TempTable ancora in giro dopo le uscite Foo?

Se è così, foo poteva mancare la prossima volta che viene chiamato, perché TempTable sarebbe già esistere. Come che dovrebbe essere gestito.

EDIT: Sto usando Informix 11.5

È stato utile?

Soluzione 3

Alla fine ho usato una variazione di Jonathan e la soluzione di RET:

CREATE PROCEDURE foo ()
    ON EXCEPTION IN (-206)
    END EXCEPTION WITH RESUME;

    DROP TABLE tempTable;    

    SELECT * FROM fooBar INTO TEMP tempTable;

    -- do something with tempTable here

    DROP TABLE tempTable;
END PROCEDURE;

Altri suggerimenti

Come altri hanno dichiarato, tabelle temporanee ultima fino a quando non li cadere in modo esplicito o la sessione termina.

Se la stored procedure non riesce perché la tabella esiste già, SPL genera un'eccezione. Si può trattare con le eccezioni con l'aggiunta di una clausola ON ECCEZIONE -. Ma si stanno inserendo una delle parti più barocche di SPL, Stored Procedure Lingua

Ecco una versione leggermente modificata della stored procedure - quella che genera una divisione per un'eccezione zero (SQL -1202):

CREATE PROCEDURE foo ()
    define i integer;
    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;
END PROCEDURE;

execute procedure foo();
SQL -1202: An attempt was made to divide by zero.

execute procedure foo();
SQL -958: Temp table temptable already exists in session.

Ciò dimostra che la prima volta attraverso il codice eseguito SELECT, creando la tabella, e poi corse intervento della divisione per zero. La seconda volta, però, la SELEZIONA non è riuscita perché la tabella temporanea esisteva già, da cui il messaggio di errore diverso.

drop procedure foo;
CREATE PROCEDURE foo()
    define i integer;

    BEGIN
        ON EXCEPTION
            DROP TABLE tempTable;
            SELECT * FROM 'informix'.systables INTO TEMP tempTable;
        END EXCEPTION WITH RESUME;
        SELECT * FROM 'informix'.systables INTO TEMP tempTable;
    END;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;
END PROCEDURE;

Il blocco BEGIN / END limita la gestione alla dichiarazione intrappolato eccezione. Senza il BEGIN / END, la gestione delle eccezioni copre l'intera procedura, reagendo alla divisione per zero troppo (e quindi lasciando che il lavoro DROP TABLE e la procedura sembra funzionare correttamente).

Si noti che TempTable esiste ancora a questo punto:

+ execute procedure foo();
SQL -1202: An attempt was made to divide by zero.
+ execute procedure foo();
SQL -1202: An attempt was made to divide by zero.

Ciò dimostra che il procedimento non riesce perché la tabella temporanea è presente.

È possibile limitare il blocco ON eccezione a codici di errore selezionati (-958 sembra plausibile per questo) da:

ON EXCEPTION IN (-958) ...

Vedere la Guida Informix IBM per SQL:. Sintassi manuale, capitolo 3 Bilancio SPL '

Si noti che Informix 11.70 ha aggiunto il 'Se non esiste' e 'SE NON ESISTE' clausole di creare e DROP. Così, è possibile utilizzare la modifica GOCCIA TABLE :

DROP TABLE IF EXISTS tempTable;

In questo modo, con Informix 11.70 o poi, il modo più semplice di scrivere la procedura è:

DROP PROCEDURE IF EXISTS foo;

CREATE PROCEDURE foo()
    define i integer;
    DROP TABLE IF EXISTS tempTable;

    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;  -- Still a good idea
END PROCEDURE;

Si potrebbe anche usare questo, ma poi si arriva alla definizione precedente del procedimento, qualunque cosa fosse, e potrebbe non essere quello che vi aspettavate.

CREATE PROCEDURE IF NOT EXISTS foo()
    define i integer;
    DROP TABLE IF EXISTS tempTable;

    SELECT * FROM 'informix'.systables INTO TEMP tempTable;

    -- do something with tempTable here
    let i = 1 / 0;

    DROP TABLE tempTable;  -- Still a good idea
END PROCEDURE;

Secondo la documentazione , tabelle temporanee vengono eliminate al termine della sessione.

Sì, la tabella temporanea esisterà ancora. tabelle temporanee per definizione hanno una durata della sessione che li ha creati, se non esplicitamente caduto.

La tabella temporanea può essere visto solo dalla sessione che lo ha creato, e non v'è alcun impedimento alla stessa procedura viene eseguito in parallelo da più utenti. La risposta di Adamo di prova per l'esistenza della tabella temporanea restituirà un risultato diverso da zero se qualsiasi utente è in esecuzione la procedura. È necessario verificare che la sessione che possiede il tavolo temp è la sessione corrente pure. Dato che la questione rientra nell'ambito di applicazione di una stored procedure, potrebbe essere più semplice per aggiungere un calo esplicita, avvolto in una certa gestione delle eccezioni.

SELECT count(*) 
INTO w_count 
FROM sysmaster:systabnames s,sysmaster:systabinfo i
WHERE i.ti_partnum = s.partnum
AND sysmaster:BITVAL(i.ti_flags,'0x0020') = 1
AND s.tabname = 'tempTable' ;

Se w_count è 1, eliminare tavolo prima di SELECT ... INTO. Stessa cosa con DROP TABLE.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top