在 PL/SQL 中创建临时表
我正在使用 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,而不是将其作为一个脚本运行。这样可以吗?)
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 #PatientIDs)
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?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Oracle 有临时表,但它们需要显式创建:
临时表中的数据对于创建它的会话来说是私有的,并且可以是特定于会话或特定于事务的。如果在会话结束之前不会删除数据,则需要在创建语句末尾使用
ON COMMIT PRESERVE ROWS
。也没有对它们的回滚或提交支持...我认为在您给出的示例中不需要临时表 - 由于临时表正在填充,因此可能无法对 APPOINTMENTS 表进行更新得到反映。使用 IN/EXISTS/JOIN:
如果有多个 APPOINTMENT 记录与单个 PERSON 记录关联,则 JOINing 存在重复风险,这就是我添加 DISTINCT 的原因。
Oracle has temporary tables, but they require explicit creation:
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: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 不具备像 SQL Server 那样随意创建临时表的功能。您必须在数据库架构中显式创建表(
创建全局临时表
)。这也意味着您需要允许创建表的权限,并且必须将脚本显式部署为数据库更改。该表在全局名称空间中也是可见的。这是 Oracle 和 SQL Server 编程之间显着的惯用差异。惯用的 T-SQL 可以广泛使用临时表,并且真正需要编写过程 T-SQL 代码的情况相当罕见,这主要是因为这种便利。
惯用的 PL/SQL 会更快地退出过程代码,并且这样做可能比尝试伪造临时表更好。请注意,PL/SQL 具有面向性能的构造,例如用于对游标和嵌套结果集(游标表达式)进行显式并行处理的流控制;最近的版本有一个 JIT 编译器。
您可以使用一系列工具来使过程 PL/SQL 代码快速运行,这可以说是惯用的 PL/SQL 编程。底层范例与 T-SQL 有所不同,临时表的方法是系统架构和编程习惯不同的主要点之一。
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.
虽然确切的问题已经解决,但如果您想在该领域建立一些有用的技能,我会看看 PL/SQL 集合,特别是使用 pl/sql 集合的批量 SQL 操作(BULK COLLECT / Bulk Binds), RETURNING 子句,并使用 %ROWTYPE 定义集合。
通过理解上述所有内容,您可以显着减少编写的 pl/sql 代码量 - 尽管始终记住全 SQL 解决方案几乎总是会击败 PL/SQL 解决方案。
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.