Apache Spark SQL CREATE VIEW 语法详解:持久化视图、临时视图与 Schema 演化策略

发布时间:2026/9/19 5:03:50

Apache Spark SQL CREATE VIEW 语法详解:持久化视图、临时视图与 Schema 演化策略 Apache Spark SQL CREATE VIEW 语法详解持久化视图、临时视图与 Schema 演化策略【免费下载链接】sparkApache Spark - A unified analytics engine for large-scale data processing项目地址: https://gitcode.com/gh_mirrors/sp/spark本篇围绕 Apache Spark SQL 的CREATE VIEW语句展开系统讲解其完整语法、全部参数选项OR REPLACE、[ GLOBAL ] TEMPORARY、IF NOT EXISTS、列注释、WITH SCHEMA等、临时视图的命名空间规则以及持久化视图冻结 SQL Path 的机制。读完本文你将能够正确编写各类视图 DDL并结合sql/catalyst与sql/core的解析器源码理解每个参数在引擎内部的落地方式与错误边界。一、视图是什么只有元数据的虚拟表Spark SQL 中的视图View基于一个SELECT查询的结果集构建。CREATE VIEW创建的是一张虚拟表——它本身不持有物理数据因此后续对它的ALTER VIEW、DROP VIEW等操作都只修改元数据而不会触碰任何数据文件。从实现上看CREATE VIEW语句经过 ANTLR 解析后最终会被解析为一个CreateViewCommand逻辑计划节点。在 CreateViewCommand 定义 中可以清楚看到这一命令携带的全部元数据字段case class CreateViewCommand( name: TableIdentifier, // 视图名含 catalog/db 限定 userSpecifiedColumns: Seq[(String, Option[String])], // 列名及列级注释 comment: Option[String], // 视图级注释 collation: Option[String], // 默认排序规则 properties: Map[String, String], // TBLPROPERTIES 键值对 originalText: Option[String], // 原始 SQL 文本 plan: LogicalPlan, // 视图体的查询计划 allowExisting: Boolean, // IF NOT EXISTS replace: Boolean, // OR REPLACE viewType: ViewType, // 持久化 / 临时 / 全局临时 viewSchemaMode: ViewSchemaMode SchemaUnsupported, // WITH SCHEMA 策略 isAnalyzed: Boolean false, referredTempFunctions: Seq[String] Seq.empty)viewType与viewSchemaMode两个字段分别对应下文的TEMPORARY与WITH SCHEMA参数是理解CREATE VIEW行为的两个核心开关。二、完整语法BNFCREATE VIEW的语法定义如下引自 CREATE VIEW 官方参考CREATE [ OR REPLACE ] [ [ GLOBAL ] TEMPORARY ] VIEW [ IF NOT EXISTS ] view_identifier create_view_clauses AS query对应到 ANTLR 语法文件 SqlBaseParser.g4 中的createView规则| CREATE (OR REPLACE)? (GLOBAL? TEMPORARY)? VIEW (IF errorCapturingNot EXISTS)? identifierReference identifierCommentList? (commentSpec | schemaBinding | collationSpec | (PARTITIONED ON identifierList) | (TBLPROPERTIES propertyList))* AS query #createView注意两点与文档的对应关系create_view_clauses在语法层面是一个可重复的组(...)*其中可包含commentSpec、schemaBinding、collationSpec即DEFAULT COLLATION与TBLPROPERTIES因此各子句顺序不敏感语法层面虽然存在PARTITIONED ON identifierList分支但解析器会显式拒绝它——在 SparkSqlParser.visitCreateView 中有如下校验if (!ctx.identifierList.isEmpty) { invalidStatement(CREATE VIEW ... PARTITIONED ON, ctx) }即视图不支持PARTITIONED ON子句这与视图无物理分区数据的设计一致。此外解析器还会对重复子句做统一检查checkDuplicateClauses并对IF NOT EXISTS与OR REPLACE同时出现抛出createViewWithBothIfNotExistsAndReplaceError。三、参数详解3.1 OR REPLACE若同名视图已存在则用新定义替换旧定义。对应CreateViewCommand.replace字段。它与IF NOT EXISTS互斥二者同时书写会在解析阶段直接报错。3.2 [ GLOBAL ] TEMPORARYTEMPORARY视图是会话session作用域的会话结束时自动删除底层元存储metastore中不会持久化任何条目。它存在于每个会话私有的system.session命名空间中。GLOBAL TEMPORARY视图则绑定到系统保留的临时数据库global_temp跨会话可见但同样不落持久化元存储。视图类型由CreateViewCommand中的viewType: ViewType区分该命令通过混入 CreateTempView 特质统一处理临时视图的注册与清理逻辑。3.3 IF NOT EXISTS仅当视图不存在时才创建否则忽略不报错。注意TEMPORARY视图尚不支持IF NOT EXISTS。3.4 view_identifier持久化视图与临时视图的命名规则差异持久化视图的命名可选带数据库名或 catalog 数据库名限定不带限定时在当前 schema 中创建[ catalog_name. ] [ database_name. ] view_name临时视图的命名只能被会话 schemasession或system.session限定其他任何限定都会被拒绝并抛出INVALID_TEMP_OBJ_QUALIFIER错误。该规则由解析器中的normalizeTempViewIdentifier函数强制执行见 SparkSqlParser.scala/** * Normalizes a multi-part identifier for CREATE/DROP TEMPORARY VIEW. * Allows: 1-part (v), 2-part session.v, 3-part system.session.v. * Returns the single view name. Throws INVALID_TEMP_OBJ_QUALIFIER for invalid qualifiers. */ private def normalizeTempViewIdentifier( viewIdentifier: Seq[String], ctx: ParserRuleContext): String { viewIdentifier.length match { case 1 viewIdentifier.head case 2 if (viewIdentifier.head.equalsIgnoreCase(CatalogManager.SESSION_NAMESPACE)) { viewIdentifier.last } else { throw QueryParsingErrors.invalidTempObjQualifierError( VIEW, viewIdentifier.last, viewIdentifier.head, ctx) } case 3 if (viewIdentifier(0).equalsIgnoreCase(CatalogManager.SYSTEM_CATALOG_NAME) viewIdentifier(1).equalsIgnoreCase(CatalogManager.SESSION_NAMESPACE)) { viewIdentifier.last } else { throw QueryParsingErrors.invalidTempObjQualifierError( VIEW, viewIdentifier.last, viewIdentifier.init.mkString(.), ctx) } case _ throw QueryParsingErrors.invalidTempObjQualifierError( VIEW, viewIdentifier.last, viewIdentifier.init.mkString(.), ctx) } }对应的错误定义在 QueryParsingErrors.scala错误类为INVALID_TEMP_OBJ_QUALIFIER携带objectType、objectName、qualifier三个参数。同一套规范化逻辑也用于临时函数FUNCTION可见 SparkSqlParser.scala 中的同名分支。完全限定视图名在其 schema 内必须唯一。3.5 create_view_clauses可选且顺序不敏感的子句子句作用限制( column_name [ COMMENT column_comment ], ... )指定列级注释可附带列名重命名无COMMENT view_comment指定视图级注释无TBLPROPERTIES ( key value [ , ... ] )附加元数据键值对不能与TEMPORARY视图同时使用WITH SCHEMA { BINDING \| COMPENSATION \| [ TYPE ] EVOLUTION }指定视图对底层 schema 变化的容忍策略不支持TEMPORARY视图两个限制都能在解析器中找到直接证据见 visitCreateViewif (ctx.TEMPORARY ! null !properties.isEmpty) { operationNotAllowed(TBLPROPERTIES cant coexist with CREATE TEMPORARY VIEW, ctx) }WITH SCHEMA 的四种模式WITH SCHEMA子句控制当基表 schema 发生变化时视图如何反应对应CreateViewCommand.viewSchemaMode: ViewSchemaMode字段BINDING— 视图只容忍底层 schema 中安全上转safe up-cast类的类型变化COMPENSATION— 视图容忍需要显式 cast 的类型变化但运行期可能出现转换错误TYPE EVOLUTION— 视图自适应底层 schema 的任意类型变化EVOLUTION— 若视图定义没有列清单则任何 schema 变化包括SELECT *查询下被增删的列都会被视图吸收若视图定义了列清单该子句按TYPE EVOLUTION解释。默认值为WITH SCHEMA COMPENSATION。该行为在 DDLParserSuite 等测试中有针对性验证CreateViewCommand的viewSchemaMode参数默认值为SchemaUnsupported代表解析未指定时的兜底状态具体模式在分析阶段被填充为文档所述的COMPENSATION。3.6 query 子句query是一条 SELECT 语句用于从基表或其他视图构造视图。关键约束持久化视图不能引用临时视图、临时函数或会话变量——否则视图体无法在跨会话复用持久化视图会在CREATE VIEW时把当时生效的 SQL Path **固化frozen**进视图元数据此后每次引用视图时视图体都按这个冻结的 path 解析而不是调用者当前会话的 path。可用 DESCRIBE EXTENDED 查看捕获到的 path机制见 SET PATH。四、完整示例4.1 带注释的持久化视图、全局临时视图与 EVOLUTION 视图-- Create or replace view for experienced_employee with comments. CREATE OR REPLACE VIEW experienced_employee (ID COMMENT Unique identification number, Name) COMMENT View for experienced employees AS SELECT id, name FROM all_employee WHERE working_years 5; -- Create a global temporary view subscribed_movies. CREATE GLOBAL TEMPORARY VIEW subscribed_movies AS SELECT mo.member_id, mb.full_name, mo.movie_title FROM movies AS mo INNER JOIN members AS mb ON mo.member_id mb.id; -- Create a view filtering the orders table which will adjust to schema changes in orders. CREATE OR REPLACE VIEW open_orders WITH SCHEMA EVOLUTION AS SELECT * FROM orders WHERE status open;第一个示例同时演示了列清单含列重命名ID、Name、列级COMMENT与视图级COMMENT第二个演示绑定到global_temp的全局临时视图第三个演示WITH SCHEMA EVOLUTION当orders表增删列时视图自动适应。4.2 临时视图的会话限定符-- Unqualified, session-qualified, and system.session-qualified names all create the same -- temporary view in the per-session system.session namespace. CREATE TEMPORARY VIEW recent_orders AS SELECT * FROM orders WHERE order_date current_date - INTERVAL 7 DAYS; CREATE OR REPLACE TEMPORARY VIEW session.recent_orders AS SELECT * FROM orders WHERE order_date current_date - INTERVAL 7 DAYS; CREATE OR REPLACE TEMPORARY VIEW system.session.recent_orders AS SELECT * FROM orders WHERE order_date current_date - INTERVAL 7 DAYS; -- All three names address the same temporary view: SELECT count(*) FROM recent_orders; SELECT count(*) FROM session.recent_orders; SELECT count(*) FROM system.session.recent_orders; -- DROP VIEW accepts the same qualifiers (there is no DROP TEMPORARY VIEW form): DROP VIEW session.recent_orders; -- Any other qualifier on a TEMPORARY view is rejected. CREATE TEMPORARY VIEW mydb.bad_temp AS SELECT 1; [INVALID_TEMP_OBJ_QUALIFIER] qualifier mydb is not allowed for temporary VIEW ... CREATE TEMPORARY VIEW system.builtin.bad_temp AS SELECT 1; [INVALID_TEMP_OBJ_QUALIFIER] qualifier system.builtin is not allowed for temporary VIEW ...这段示例与源码一一对应normalizeTempViewIdentifier接受一段式、session.v两段式、system.session.v三段式共三种形态其余任何限定如mydb、system.builtin都会命中invalidTempObjQualifierError分支抛出INVALID_TEMP_OBJ_QUALIFIER。另外注意删除临时视图没有独立的DROP TEMPORARY VIEW形式统一走 DROP VIEW 并使用相同的限定符。五、冻结 SQL PathCREATE VIEW 时刻的路径快照持久化视图会捕获CREATE VIEW时刻生效的 SQL Path。此后无论调用方会话如何切换 PATH视图体始终按冻结路径解析未限定名称。官方文档给出的完整演示如下来自 CREATE VIEW 参考 CREATE SCHEMA views_a; CREATE SCHEMA views_b; CREATE TABLE views_a.t USING parquet AS SELECT 1 AS id; CREATE TABLE views_b.t USING parquet AS SELECT 2 AS id; -- The PATH at CREATE VIEW time points at views_a, so unqualified t in the view body binds to -- views_a.t. SET PATH spark_catalog.views_a, system.builtin; CREATE VIEW default.v_frozen AS SELECT id FROM t; -- Flip the live PATH. The view body still resolves t against the frozen path. SET PATH spark_catalog.views_b, system.builtin; -- A bare query follows the LIVE path: SELECT id FROM t; 2 -- The view body follows its FROZEN path: SELECT id FROM default.v_frozen; 1 -- DESCRIBE EXTENDED shows the captured path: DESCRIBE EXTENDED default.v_frozen; ... SQL Path spark_catalog.views_a, system.builtin这个例子清晰地展示了活路径 vs 冻结路径的分离切换PATH后裸查询SELECT id FROM t命中views_b.t返回 2而视图default.v_frozen仍命中views_a.t返回 1DESCRIBE EXTENDED输出中的SQL Path行即为捕获时点的快照。这一特性保证了跨会话、跨作业引用视图时名称解析的确定性避免同一视图在不同客户端看到不同表的歧义。机制细节参见 SET PATH。六、验证与源码入口如果你想在自己的环境中验证本文内容可关注以下仓库位置均为查看用途仓库为只读语法定义SqlBaseParser.g4 中CREATE ... VIEW ... AS query规则解析与参数校验SparkSqlParser.visitCreateView包括PARTITIONED ON拒绝、重复子句检查、IF NOT EXISTS/OR REPLACE互斥、临时视图禁用TBLPROPERTIES临时视图限定符规范化normalizeTempViewIdentifier 与 invalidTempObjQualifierError命令模型CreateViewCommand其viewType/viewSchemaMode字段对应TEMPORARY与WITH SCHEMA两个参数行为测试CreateViewSuiteBase、v1 版本 CreateViewSuite、v2 版本 CreateViewSuite以及解析层测试 DDLParserSuite。七、相关语句ALTER VIEWDROP VIEWSHOW VIEWSSET PATH名称解析Name Resolution【免费下载链接】sparkApache Spark - A unified analytics engine for large-scale data processing项目地址: https://gitcode.com/gh_mirrors/sp/spark创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/19 5:03:50

LLM驱动的非结构化沟通记录自动抽取与CRM批量写入工程实践

从一线开发的视角聊聊这个项目吧。背景很简单,我们团队负责的CRM系统里,销售、客服日常有大量非结构化沟通记录——客户微信聊天、邮件往来、电话录音转写、展会名片照片里的备注,这些信息全都埋在一堆口语化、碎片化的文本里。以前靠人工录入…

2026/9/19 5:03:50

主流AI工具横向评测:性能、质量与成本分析

1. 项目背景与测试初衷去年第三季度开始,我陆续收到读者关于AI工具选择的咨询请求。作为长期关注智能技术落地的从业者,我决定系统性地对当前主流AI工具进行横向评测。这次测试覆盖了文本生成、图像处理、数据分析等六大应用场景,累计耗时4个…

2026/9/19 4:58:49

Unity 2D平滑转向实战:旋转矩阵、四元数与最短路径插值

在2D游戏开发里,角色转向这件事看起来简单,做起来却很容易翻车。我见过太多项目,角色移动逻辑写得没问题,但一到转向就露馅:要么是瞬间翻转像抽搐,要么是角度插值走最短路径时突然绕远路,要么是…

2026/9/19 5:53:51

绕过API限制:OpenClaw实现主流AI网页端直接调用

1. 项目背景与核心价值最近在折腾AI工具时发现一个痛点:很多大模型网页端明明能用,但想集成到自己的项目里就得折腾API。要么要申请权限,要么要处理复杂的鉴权流程,甚至有些服务压根不开放API。OpenClaw这个项目正好解决了这个问题…

2026/9/19 5:53:51

Flutter与OpenHarmony游戏拖尾特效实现与优化

1. 项目概述:Flutter与OpenHarmony下的游戏拖尾特效实现在移动游戏开发中,视觉反馈的即时性和表现力直接影响玩家的游戏体验。轨迹拖尾特效(Trail Effect)作为一种常见的视觉增强手段,能够有效提升动态物体的运动感知。…

2026/9/19 5:53:51

Jetson边缘AI实战复盘:从系统烧录到YOLOv5与Qwen大模型部署全链路

1. 为什么值得做一次系统复盘Jetson边缘嵌入式实战课程走到第十讲,回头把前九讲的内容串一遍,这件事本身就比再学一个新模型更有价值。我见过太多人学Jetson的方式是“东一榔头西一棒槌”——今天跟着教程刷个系统,明天抄个YOLOv5的部署脚本&…

2026/9/19 5:53:51

嵌入式系统第一性原理:从SPI、I2C到DMA的工程实践

嵌入式系统这个领域有个很有意思的现象:很多人能照着教程把外设跑通,但一旦项目换了芯片、换了传感器,或者时序上出了点玄学问题,就完全不知道从哪里下手。我自己带过不少新人,也做过从8位机到Cortex-M7的各种板子&…

2026/9/19 5:48:51

Codex CLI 安装配置全指南:macOS/Windows/IDE 报错排查

1. 先搞清楚:你装的 Codex 到底是哪一层的东西第一次接触 Codex 的朋友,十个里有八个会在“下载哪个、装哪个”上绕弯子。因为 Codex 这个名字现在同时指几样东西:一个是 CLI 命令行工具,可以通过终端和它对话,让它直接…

2026/9/18 14:13:01

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/19 0:03:10

验证 OpenSpec 兼容性,Cursor 的 Token 从 TaoToken 出

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 0:03:10

书桌角落的 Mac mini,OpenClaw 通过 TaoToken 跑任务。

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 0:03:10

oh-my-hermes:打造跨工具的命令编排与插件化工作流

1. 项目概述与设计初衷1.1 它到底是什么先说结论:oh-my-hermes 是一个面向开发者日常终端操作的效率工具套件,核心定位是“把分散在各类命令行工具里的高频操作,统一收拢成一套插件化、可编排的工作流”。项目灵感来源很明显——oh-my-zsh 重…

2026/9/18 14:13:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/18 14:13:02

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/18 14:13:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码