Create a temp table in PL/SQL
I'm working with an Oracle 10g database, and I want to extract a group of records from one table, and then use that for pulling records out of a bunch of related tables.
If this were T-SQL, I'd do it something like this:
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 #PatientID开发者_运维知识库s)
DROP TABLE #PatientIDs
However, all the helpful pages I look at make this look like a lot more work than it could possibly be, so I think I must be missing something obvious.
(BTW, instead of running this as one script, I'll probably open a session in Oracle SQL Developer, create the temp table, and then run each query off it, exporting them to CSV as I go along. Will that work?)
Oracle has temporary tables, but they require explicit creation:
create global temporary table...
The data in a temporary table is private for the session that created it and can be session-specific or transaction-specific. If data is not to be deleted until the session ends, you need to use ON COMMIT PRESERVE ROWS
at the end of the create statement. There's also no rollback or commit support for them...
I see no need for temp tables in the example you gave - it risks that updates made to the APPOINTMENTS
table since the temp table was populating won't be reflected. Use IN/EXISTS/JOIN:
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
JOINing risks duplicates if there are more than one APPOINTMENT records associated to a single PERSON record, which is why I added the DISTINCT.
Oracle doesn't have the facility to casually create temporary tables in the same way as SQL Server. You have to create the table explicitly in the database schema (create global tempory table
). This also means that you need permissions that allow you to create tables, and the script must explicitly be deployed as a database change. The table is also visible in a global name space.
This is a significant idiomatic difference between Oracle and SQL Server programming. Idiomatic T-SQL can make extensive use of tempory tables and genuine requirements to write procedural T-SQL code are quite rare, substantially because of this facility.
Idiomatic PL/SQL is much quicker to drop out to procedural code, and you would probably be better off doing this than trying to fake temporary tables. Note that PL/SQL has performance oriented constructs such as flow control for explicit parallel processing over cursors and nested result sets (cursor expressions); recent versions have a JIT compiler.
You have access to a range of tools to make procedural PL/SQL code run quickly, and this is arguably idiomatic PL/SQL programming. The underlying paradigm is somewhat different from T-SQL, and the approach to temporary tables is one of the major points where the system architecture and programming idioms differ.
While the exact problem has been solved, if you want to build up some useful skills in this area, I would take a look at PL/SQL Collections, and particularly bulk SQL operations using pl/sql collections (BULK COLLECT / Bulk Binds), the RETURNING clause, and defining collections using %ROWTYPE.
You can dramatically reduce the amount of pl/sql code you write through understanding all the above - although always remember that an all-SQL solution will almost always beat a PL/SQL one.
精彩评论