2009-12-02 13 views
9

Ho la seguente procedura:durata della vita di tabella temporanea

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

    -- do something with tempTable here 

    DROP TABLE tempTable; 
END PROCEDURE; 

Cosa succede se c'è un'eccezione prima che il DROP TABLE si chiama? Si troverà ancora tempting dopo le uscite di foo?

Se è così, foo potrebbe fallire la prossima volta che viene chiamato, perché tempTable esisterebbe già. Come dovrebbe essere gestito.

EDIT: Sto usando Informix 11,5

risposta

3

fine ho utilizzato una variante 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; 
+0

Quello che hai qui - rilascia la tabella ma ignora l'errore se non esiste - è un buon modo per andare. In circostanze normali, manca la tabella temporanea prima dell'esecuzione e dopo il completamento. Sarebbe possibile modificare l'ambito dell'eccezione, ma dovrebbe funzionare correttamente. –

+0

Nota che Informix moderna supporta le clausole IF EXISTS e IF NOT EXISTS in istruzioni come DROP TABLE. Quindi, in questi giorni, potresti scrivere: 'DROP TABLE IF EXISTS tempTable;' che lascerà cadere la tabella se è presente (e tu hai il permesso, ecc.) E non fare nulla se la tabella non esiste. –

3

According to the documentation, le tabelle temporanee sono interrotte Se al termine della sessione.

+0

credo, la mia preoccupazione è che la sessione termina quando la connessione è chiusa (? Destra). Quindi, se pippo viene chiamato più volte prima che la connessione venga chiusa, e la prima invocazione a pippo abbia generato un'eccezione e non abbia ripulito la tabella temporanea, la successiva invocazione di pippo fallirà, poiché la tabella temporanea esiste già. Qual è la migliore pratica per il codice da proteggere da questo. Dobbiamo verificare se esiste la tabella temporanea e rilasciarla? – rouble

+0

Ho inserito il codice "verifica se la tabella esiste" per il controllo prima di creare e rilasciare. Informix ha una struttura di tabella temporanea in cui una tabella può essere vista solo dalla sessione specifica? SQL Server ha questa funzionalità. – adamcodes

1
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 la tabella prima di SELEZIONARE ... INTO. Lo stesso con DROP TABLE.

2

Sì, la tabella temporanea continuerà a esistere. Le tabelle temporali per definizione hanno una durata della sessione che le ha create, a meno che non vengano eliminate esplicitamente.

La tabella temporanea può essere vista solo dalla sessione che l'ha creata e non vi è alcun impedimento alla stessa procedura eseguita in parallelo da più utenti. La risposta di Adam per verificare l'esistenza della tabella temporanea restituirà un risultato diverso da zero se qualsiasi utente sta eseguendo la procedura. È necessario verificare che la sessione che possiede la tabella temporanea sia anche la sessione corrente. Dato che questa domanda rientra nell'ambito di una procedura memorizzata, potrebbe essere più semplice aggiungere un DROP esplicito, racchiuso in una gestione delle eccezioni.

+0

Presumo che intendi qualcosa del genere: CREATE PROCEDURE droptempTtable() ON ECCEZIONE IN ECCEZIONE (-206) END; DROP TABLE tempTable; PROCEDURA FINE; Esiste un modo per sapere come specificare il nome della tabella, per rendere generica questa procedura? – rouble

4

Come altri hanno dichiarato, le tabelle temporanee durano fino a quando non le rilasciate esplicitamente o la sessione termina.

Se la stored procedure non riesce perché la tabella esiste già, SPL genera un'eccezione. È possibile gestire eccezioni aggiungendo una clausola ON EXCEPTION, ma si entra in una delle parti più barocche di SPL, Stored Procedure Language.

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. 

Questo dimostra che la prima volta attraverso il codice eseguito la SELECT, creando il tavolo, e poi ha eseguito fallo della divisione per zero. La seconda volta, tuttavia, la SELECT non è riuscita perché la tabella temporanea esisteva già, quindi il diverso messaggio di errore.

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 delle eccezioni all'istruzione intrappolata. Senza BEGIN/END, la gestione delle eccezioni copre l'intera procedura, reagendo anche all'errore di divisione per zero (e quindi lasciando funzionare DROP TABLE e la procedura sembra funzionare correttamente).

noti che temptable ancora presente in tale 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) ... 

consultare la Guida Informix IBM per SQL: sintassi manuale, capitolo 3 Bilancio SPL ' .

Nota che Informix 11.70 ha aggiunto il 'IF EXISTS' e 'SE NON ESISTE' clausole di creare e Istruzioni DROP. Così, è possibile utilizzare la modifica DROP TABLE dichiarazione:

DROP TABLE IF EXISTS tempTable; 

Così, 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 ottenere la definizione precedente della procedura, qualunque essa fosse, e potrebbe non essere quello che ti aspettavi.

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; 
+0

@ Jonathan Ho usato una variazione di ciò che hai suggerito qui. Ho presentato quello che ho usato come risposta. Fatemi sapere se avete commenti su quel spl/sql. – rouble

Problemi correlati