我正在使用Oracle 10g数据库,我想从一个表中提取一组记录,然后使用它来从一堆相关表中提取记录。
如果这是T-SQL,我会这样做:
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
然而,我看到的所有有用的页面都让它看起来比它可能的工作要多得多,所以我想我一定会错过一些明显的东西。
(顺便说一句,我可能会在Oracle SQL Developer中打开一个会话,创建临时表,然后运行每个查询,然后将它们导出到CSV中。而不是将其作为一个脚本运行。工作?)
答案 0 :(得分:12)
Oracle有临时表,但它们需要显式创建:
create global temporary table...
临时表中的数据对于创建它的会话是私有的,可以是特定于会话的或特定于事务的。如果要在会话结束前删除 数据,则需要在create语句末尾使用ON COMMIT PRESERVE ROWS
。它们也没有回滚或提交支持......
我认为你给出的示例中不需要临时表 - 因为临时表的填充不会反映出对APPOINTMENTS
表所做的更新的风险。使用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
如果有多个APPOINTMENT记录与单个PERSON记录关联,则加入风险重复,这就是我添加DISTINCT的原因。
答案 1 :(得分:6)
Oracle没有以与SQL Server相同的方式随意创建临时表的功能。您必须在数据库模式(create global tempory table
)中显式创建表。这也意味着您需要允许创建表的权限,并且必须将脚本显式部署为数据库更改。该表在全局名称空间中也可见。
这是Oracle和SQL Server编程之间的重要区别。惯用语T-SQL可以广泛使用临时表,并且编写程序性T-SQL代码的真正要求非常少见,主要是因为这种设施。
惯用PL / SQL可以更快地退出程序代码,你可能会比尝试伪造临时表更好。请注意,PL / SQL具有面向性能的构造,例如用于对游标进行显式并行处理的流控制和嵌套结果集(游标表达式);最新版本有一个JIT编译器。
您可以访问一系列工具来快速运行程序PL / SQL代码,这可以说是惯用的PL / SQL编程。底层范例与T-SQL略有不同,临时表的方法是系统架构和编程习惯不同的主要方面之一。
答案 2 :(得分:5)
虽然确切的问题已经解决了,如果你想在这方面建立一些有用的技能,我会看看PL / SQL集合,特别是使用pl / sql集合的批量SQL操作(BULK COLLECT / Bulk)绑定),RETURNING子句,以及使用%ROWTYPE定义集合。
通过了解上述所有内容,您可以大大减少您编写的pl / sql代码的数量 - 尽管始终记住,全SQL解决方案几乎总是胜过PL / SQL解决方案。