导读:本期聚焦于长沙GEO公司创作的《DB2全局临时表与声明式临时表有什么区别?如何正确创建和使用?》,敬请观看详情。DB2中的临时表是处理中间数据的常用手段,但全局临时表和声明式临时表在使用方式和适用场景上有明显差异。本文将从创建语法入手,详细讲解两种临时表的定义方式、会话级数据隔离原理、DGTT与CGT的区别、日志与空间管理策略,并结合实际SQL示例演示如何建表、插入数据、统计行数以及自动清理机制。同时分析临时表在存储过程开发、大批量数据处理中的应用要点,指出索引创建、权限控制、统计信息收集等常见坑点,帮助你根据业务需求选择合适的临时表类型,避免运行时出现表已存在或数据串用等典型问题。

在DB2的日常开发中,临时表是承接中间计算结果的重要工具。DB2将临时表分为两大类:全局临时表(Declared Global Temporary Table,简称DGTT)和创建式全局临时表(Created Global Temporary Table,简称CGTT)。不少开发者对这两者的区别一知半解,常常在存储过程里用错类型,导致出现"SQL0601N 表已存在"或者数据串用的报错。这篇文章就把两种临时表的语法、底层机制和适用场景一次性讲清楚。

DB2全局临时表与声明式临时表有什么区别?如何正确创建和使用?

一、两种临时表的基本概念与创建语法

首先要明确一点:DB2官方文档中所说的DGTT(声明式全局临时表)和CGTT(创建式全局临时表)都属于"全局临时表"这个大类。所谓全局,指的是表定义对所有会话可见或者可创建,而不是说数据全局共享。恰恰相反,临时表的数据永远都是会话私有的,不同会话各自看到各自的数据副本,这一点后面会详细展开。

两者的核心区别在于定义的存放位置和生命周期。DGTT的表定义不存放在系统目录表中,它只在当前会话(或者说当前连接)内有效,会话断开后表定义自动消失。而CGTT的表定义是持久化的,存放在SYSIBM.SYSTABLES等系统目录里,一旦创建,所有会话都可以直接引用它,只有数据是会话隔离的。DGTT的创建语法如下:

-- 声明式全局临时表
DECLARE GLOBAL TEMPORARY TABLE session.tmp_order (
    order_id   BIGINT NOT NULL,
    cust_id    INTEGER,
    amount     DECIMAL(12,2),
    create_time TIMESTAMP
) ON COMMIT PRESERVE ROWS
  NOT LOGGED
  IN USERSPACE1;   -- 也可以省略,放入系统临时表空间

注意DECLARE语句开头的session模式,这是DGTT的固定模式名,声明时可以写也可以不写,系统默认就放在SESSION模式下。CGTT的创建语法则用的是CREATE关键字:

-- 创建式全局临时表
CREATE GLOBAL TEMPORARY TABLE admin.tmp_summary (
    dept_id    INTEGER NOT NULL,
    total_amt  DECIMAL(14,2),
    cnt        INTEGER
) ON COMMIT DELETE ROWS
  IN USERSPACE1;

这条语句执行后,表定义被持久化到数据库目录中,任何应用连接上来都可以直接INSERTSELECT这张表,而不需要先执行DECLARE。这是CGTT相对DGTT最大的便利之处:一次定义,处处可用。

二、数据隔离机制与ON COMMIT选项详解

临时表最容易被误解的一点就是数据隔离。无论是DGTT还是CGTT,DB2都会为每个会话维护一份独立的数据实例。会话A插入的行,会话B是完全看不到的,即使两个会话操作的是同一张CGTT也一样。这个隔离是基于会话级的,不需要开发者做任何额外配置。

ON COMMIT子句决定了事务提交时的行为,这是实际开发中最容易踩坑的地方。ON COMMIT DELETE ROWS表示每次COMMIT后数据自动清空,适合在一个事务内完成的短处理逻辑;ON COMMIT PRESERVE ROWS则表示COMMIT后数据保留,直到会话结束或显式DELETE。如果存储过程内部有多个事务,而中间结果需要在事务之间传递,就必须用PRESERVE ROWS,否则提交一次数据就没了,后面的步骤会莫名其妙查不到数据。

可以用一个简单的实验验证这个行为:

DECLARE GLOBAL TEMPORARY TABLE session.t_test (
    id INTEGER
) ON COMMIT DELETE ROWS NOT LOGGED;

INSERT INTO session.t_test VALUES (1), (2), (3);
SELECT COUNT(*) FROM session.t_test;  -- 返回3

COMMIT;
SELECT COUNT(*) FROM session.t_test;  -- 返回0,数据已被清空

另外还有ON ROLLBACK DELETE ROWSON ROLLBACK PRESERVE ROWS选项控制回滚时的行为,默认是PRESERVE ROWS,一般保持默认即可。还有一个NOT LOGGED参数值得注意:临时表默认就不记录日志,写入性能远高于普通表,这也是用它做大批量中间结果缓存的性能优势来源。

三、实际开发中的常见坑点与最佳实践

第一个坑是DGTT的重复声明问题。DGTT不支持CREATE OR REPLACE式的覆盖语法,如果应用程序用了连接池,同一个连接上第二次执行DECLARE就会报SQL0601N。解决办法是在声明前先判断并删除,或者把DECLARE语句放在应用初始化逻辑里只执行一次:

-- 先删除已存在的临时表(如果存在)
DROP TABLE IF EXISTS session.tmp_order;

DECLARE GLOBAL TEMPORARY TABLE session.tmp_order (
    order_id BIGINT NOT NULL,
    amount   DECIMAL(12,2)
) ON COMMIT PRESERVE ROWS NOT LOGGED;

第二个坑是索引与统计信息。DGTT可以在声明时带索引定义,或者在会话内单独CREATE INDEX,但会话结束索引也随之消失。CGTT则可以持久化地创建索引,所有会话共享索引定义。对于数据量大的中间结果集,别忘了建索引,否则复杂的关联查询可能慢得离谱。统计信息方面,CGTT可以像普通表一样执行RUNSTATS让优化器拿到准确的基数估计,这是DGTT做不到的。

第三个坑是空间管理。临时表如果显式指定了IN USERSPACE1这类用户表空间,数据会占用正式表空间的空间,建议为临时表专门建一个临时表空间或者不指定IN子句让系统分配。会话结束后空间会被释放,但如果会话异常挂起不释放,可能需要DBA介入清理。选择建议可以简单归纳为:临时性、单次批处理用DGTT;需要跨程序共享表定义、需要索引和统计信息持久化、需要在编译期校验SQL的,用CGTT。

最后补充一点权限方面的差异:CGTT的创建需要IMPLICIT_DATABASE权限或相应模式上的CREATEIN权限,访问控制走正常的授权体系;DGTT则基本不涉及授权问题,声明即用。理解了这些机制,在存储过程开发、ETL批处理等场景里就能放心地把中间结果放到临时表里,既提升了性能又避免了并发会话之间的数据干扰。

DB2临时表全局临时表声明式临时表修改时间:2026-09-04 05:54:37

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260904/50053.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。