返回
RSS Databricks Blog AI 逐段翻译 发布 2026-08-21 03:00 收录于 08-22

破解SQL迁移迷思:新SQL特性让存储过程平迁湖仓更轻松

DataHot 速览

本文针对数据仓库迁移到湖仓时,遗留存储过程等过程化SQL逻辑难以迁移的痛点,以Oracle迁移场景为例,展示如何在Databricks Lakehouse上利用新SQL特性,将原有业务逻辑逐行翻译而非用Python/Spark重写。文章强调这样既保留原逻辑,也让SQL团队继续维护自己的业务逻辑,降低迁移门槛。

为什么值得关注:数据平台迁移中存储过程重构是常见难点,本文提供无需重写的平迁思路,对湖仓迁移实践有参考价值。

本文目录 8 节
  1. 获取原始业务逻辑
  2. 现在在 Databricks 上奠定基础
  3. 然后我们处理了临时表:数据仓库迁移中的轻松胜利
  4. 游标是难点——至少我们曾这么认为
  5. 脚本逻辑并不复杂
  6. 事务是关键时刻
  7. 完整的迁移后过程
  8. 我们学到的经验

译文

AI 逐段翻译

在你的仓库某处,数百个存储过程每晚醒来,悄无声息地维持着业务运转。它们是多年前由一批早已离职的 SQL 开发人员编写的。它们有嵌套游标,动态创建临时表,将跨多个表的更新捆绑在单个事务中。而在第 47 行附近,有一条注释简单写着:“不要更改此内容。”如今已无人完全理解这些过程,但每个人都依赖它们。收入仪表板、财务结算、运营报告,所有这一切,都以某种方式追溯到这些过程化 SQL 业务逻辑层。

将数据迁移到湖仓一体已得到充分理解。瓶颈在于任何数据仓库迁移的过程化核心:存储过程、事务处理、临时表、控制流,以及大量企业仍然依赖 SQL 技能的事实。每次迁移即将开始时,这些过程就成了所有人首先指出的问题:“除非我们能以最小改动运行这些过程,否则无法迁移。我们的企业仍然重度依赖 SQL。”

因此,我们决定采用一个你可能正在考虑的场景,一个我们在迁移中见过的复合过程,并在 Lakehouse 上逐步演示。此示例基于 Oracle 迁移场景,但可应用于任何数据仓库(遗留或基于云)。

获取原始业务逻辑

此示例过程处理每日订单。它将未处理的订单暂存到临时表中,根据客户主数据验证它们,循环处理失败记录以单独记录每个拒绝原因,然后更新区域收入汇总并将所有订单标记为已处理,整个过程在失败时回滚的事务中进行。

一个不可中断的夜间作业。

此前,迁移意味着用 Python 和 Spark 完全重写。数周的工作,新出现的 bug,以及一个无法再维护自身业务逻辑的 SQL 团队。

我们没有重写,而是翻译了它。

现在在 Databricks 上奠定基础

每个过程都以签名和安全网开始。遗留代码将主体包裹在 BEGIN ... EXCEPTION ... END 中。Databricks 改用 DECLARE EXIT HANDLER FOR SQLEXCEPTION;同样的思路,语法略有不同。假设会话中已设置适当的目录和架构。

最大的区别不在于代码,而在于部署后会发生什么。在 Databricks 上,过程注册在 Unity Catalog 中,获得访问控制、列级血缘,并在所有工作区中可发现。而在当前系统中,它存在于一个只有三个人知道密码的架构中。

遗留Databricks
CREATE OR REPLACE PROCEDURE name ISCREATE OR REPLACE PROCEDURE [IF NOT EXISTS] <catalog>.<schema>.<procedure_name> ( [ procedure_parameter [, ...] ] ) [ characteristic [...] ] LANGUAGE SQL SQL SECURITY { INVOKER | DEFINER } AS BEGIN
v_id NUMBER; 在 BEGIN 之前DECLARE v_id INT; 在 BEGIN 内部
EXCEPTION WHEN OTHERS THENDECLARE EXIT HANDLER FOR SQLEXCEPTION

参考:docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-ddl-create-procedure

然后我们处理了临时表:数据仓库迁移中的轻松胜利

原始过程创建两个 临时表 用于暂存和验证失败。它们是其余逻辑所依赖的临时空间。

在 Databricks 上,这成为迁移中最简单的部分之一。无需 EXECUTE IMMEDIATE,无需 ON COMMIT PRESERVE ROWS。会话范围的 CREATE TEMP TABLE 是直接替代品,但有一个小注意事项:尚不支持 CREATE OR REPLACE TEMP TABLE,因此如果需要同一会话中可重新运行,请先删除。

参考:docs.databricks.com/aws/en/tables/temporary-tables

游标是难点——至少我们曾这么认为

这是每个人都认为需要重写的部分。原始过程逐个循环验证失败,拒绝每个错误订单,并记录原因。典型的游标模式,几十年的遗留(例如 Oracle)肌肉记忆。

自 Runtime 18.1 起,Databricks 的 SQL 脚本原生支持游标:OPEN、FETCH 和 CLOSE。 %NOTFOUND 属性变为 CONTINUE HANDLER FOR NOT FOUND循环标签和 LEAVE 替代 EXIT WHEN

脚本逻辑并不复杂

条件检查(如果没有要处理的行则跳过并记录)几乎未变。 SELECT ... INTO 变为 SET var = (SELECT ...)其余完全相同。

我们的 SQL 脚本支持完整的过程化工具集:IF/ELSE、WHILE、FOR、LOOP、REPEAT、LEAVE、ITERATE、SIGNAL/RESIGNAL。如果你的代码库包含 Teradata BTEQ 脚本,其中 .GOTO 和 .LABEL 指令映射到使用 LEAVE 和 ITERATE 的带标签循环。

参考:docs.databricks.com/aws/en/sql/language-manual/sql-ref-scripting

事务是关键时刻

这是最后一块,使迁移真正可行。原始过程更新 regiona_revenue,将订单标记为已处理,并记录批次。如果任何部分失败,全部回滚。

在遗留系统上,这是带有显式 COMMIT 的隐式事务。在 Databricks 上,BEGIN ATOMIC ... END 提供相同语义,成功自动提交,失败自动回滚,并带有一个显著优势:行级冲突检测。并发批次写入同一表仅当触及相同行时才冲突。例如,Oracle 和 Snowflake 都使用表级锁,这强制串行执行。

MERGE 语句可以原样迁移到 Databricks。显式 COMMIT 消失,因为 BEGIN ATOMIC 处理了它。团队不再担心并发批次作业相互踩踏。

采用此模式时的两个实用提示:

  • 原子块内定义的每个表都必须启用 catalogManaged 表特性。你可以就地启用现有 Delta 表:ALTER TABLE <name> SET TBLPROPERTIES('delta.feature.catalogManaged'= 'supported');
  • BEGIN ATOMIC 应位于顶层——在 SQL 脚本、笔记本单元格或 SQL 作业任务中。

参考:docs.databricks.com/aws/en/transactions/

完整的迁移后过程

相同的业务逻辑。相同的控制流。由 Unity Catalog 管理。

要在事务中运行它,请包装调用:

我们学到的经验

这些程序的迁移时间可缩短 50-75%,即使对于依赖大量 PL/SQL 包的复杂存储过程也是如此。这种效率源于机械翻译过程,该过程保持原始业务逻辑,确保 SQL 团队能无缝继续进行维护工作。除了迁移本身,团队还获得了强大的新优势:一个统一平台,其中相同的数据用于驱动仪表板、机器学习模型和 AI 计划。

要想知道你的过程能否转换,唯一的方法是尝试一个。选择你批次中最小的存储过程,最好是一个没人喜欢调试的。在工作区创建迁移项目,并开始使用 Agentic Code Convertor!

这篇内容对你有用吗?

反馈只用于改善内容筛选,不等同于收藏

分享这条资讯
分享海报
保存图片
iOS 也可以长按图片保存