2010-08-11 8 views
6

Sto lavorando con un database Oracle 10g e desidero estrarre un gruppo di record da una tabella e utilizzarlo per estrarre i record da un gruppo di tabelle correlate.Creazione di una tabella temporanea in PL/SQL

Se questo fosse T-SQL, lo farei qualcosa di simile:

CREATE TABLE #PatientIDs (
    pId int 
) 

INSERT INTO #PatientIDs 
    select distinct pId from appointments 

SELECT * from Person WHERE Person.pId IN (select pId from #PatientIDs) 

SELECT * from Allergies WHERE Allergies.pId IN (select pId from #PatientIDs) 

DROP TABLE #PatientIDs 

Tuttavia, tutte le pagine utile guardo rendono questo sembra molto più lavoro di quello che potrebbe essere, quindi penso che mi debba mancare qualcosa di ovvio.

(BTW, invece di eseguirlo come uno script, probabilmente aprirò una sessione in Oracle SQL Developer, creerò la tabella temporanea, quindi eseguirò ogni query, esportandole in CSV mentre procedo. che lavoro?)

Grazie!

+0

Perché è necessario il passaggio della tabella temporanea? Stai solo sostituendo una selezione con un'altra. La selezione iniziale è molto costosa? O è nel caso in cui una transazione concorrente cambi le cose? –

+4

Oracle non è SQL Server e le situazioni in cui è necessario utilizzare tabelle temporanee sono in realtà piuttosto rari. Per favore leggi la mia risposta a questa domanda simile: http://stackoverflow.com/questions/1192265/local-temporary-table-in-oracle-10-for-the-scope-of-stored-procedure/1193443#1193443 – APC

+0

I stava semplificando - quello che stavo cercando di fare era afferrare gli ultimi 100 pazienti (meno un po 'di duplicazione). Ma parlarne qui di seguito mi ha ricordato che stamattina avrei potuto prendere 100 pazienti a partire da mezzanotte e non dovermi preoccupare che SYSDATE cambiasse mentre procedevo. :-) – SarekOfVulcan

risposta

12

Oracle ha tabelle temporanee, ma richiedono la creazione esplicita:

create global temporary table... 

I dati in una tabella temporanea è privato per la sessione che lo ha creato e può essere specifica per una sessione o specifiche per ciascuna operazione. Se i dati sono non da eliminare fino alla fine della sessione, è necessario utilizzare ON COMMIT PRESERVE ROWS alla fine dell'istruzione create. Non c'è nemmeno rollback o supporto di commit per loro ...

Non vedo alcuna necessità di tabelle temporanee nell'esempio che hai dato - rischia che gli aggiornamenti apportati alla tabella APPOINTMENTS poiché la tabella temporanea non è stata compilata non verranno riflessi. Utilizzare IN/ESISTE/registrazione:

SELECT p.* 
    FROM PERSON p 
WHERE EXISTS (SELECT NULL 
       FROM APPOINTMENTS a 
       WHERE a.personid = a.id) 

SELECT p.* 
    FROM PERSON p 
WHERE p.personid IN (SELECT a.id 
         FROM APPOINTMENTS a) 

SELECT DISTINCT p.* 
    FROM PERSON p 
    JOIN APPOINTMENTS a ON a.id = p.personid 

unendo rischi duplicati se ci sono più di un record NOMINA associati ad un singolo record persona, che è il motivo per cui ho aggiunto il DISTINCT.

+0

Questo era il modo in cui stavo pensando di farlo inizialmente, ma lo sto filtrando per apptDate SarekOfVulcan

+0

ieri è 'apptdDate> = trunc (sysdate) -1 e apptdDate ThinkJet

5

Mentre il problema esatto è stato risolto, se si desidera sviluppare alcune utili competenze in questo ambito, darei un'occhiata alle raccolte PL/SQL e in particolare alle operazioni SQL di massa utilizzando le raccolte pl/sql (BULK COLLECT/Bulk Binds), la clausola RETURNING e la definizione delle raccolte con% ROWTYPE.

È possibile ridurre drasticamente la quantità di codice pl/sql che si scrive, comprendendo tutto quanto sopra, anche se si ricorda sempre che una soluzione SQL completa batterà quasi sempre un PL/SQL.

6

Oracle non ha la possibilità di creare casualmente tabelle temporanee nello stesso modo di SQL Server. È necessario creare la tabella esplicitamente nello schema del database (create global tempory table). Ciò significa anche che sono necessarie autorizzazioni che consentono di creare tabelle e che lo script deve essere esplicitamente distribuito come modifica del database. La tabella è anche visibile in uno spazio dei nomi globale.

Questa è una differenza idiomatica significativa tra la programmazione Oracle e SQL Server. Idiomatic T-SQL può fare ampio uso di tabelle temporanee e requisiti originali per scrivere codice T-SQL procedurale sono piuttosto rari, sostanzialmente a causa di questa funzione.

Idiomatic PL/SQL è molto più veloce da abbandonare al codice procedurale, e probabilmente sarebbe meglio farlo se non tentare di simulare tabelle temporanee. Si noti che PL/SQL ha costrutti orientati alle prestazioni come il controllo di flusso per l'elaborazione parallela esplicita su cursori e set di risultati nidificati (espressioni del cursore); le versioni recenti hanno un compilatore JIT.

È possibile accedere a una serie di strumenti per eseguire rapidamente codice procedurale PL/SQL e questa è probabilmente la programmazione PL/SQL idiomatica. Il paradigma sottostante è in qualche modo diverso da T-SQL e l'approccio alle tabelle temporanee è uno dei punti principali in cui differiscono l'architettura del sistema e gli idiomi di programmazione.