PRQL 的 from 数据源:指定关系、别名与特殊标识符的完整指南
【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址: https://gitcode.com/gh_mirrors/pr/prql
from是 PRQL 管道式查询的起点与基石——每个查询都必须由一个from语句来声明数据源,编译器会据此构建主管道(pipeline)。本文基于官方参考文档,结合 prqlc 编译器源码与集成测试,系统讲解from的基本用法、别名赋值、特殊字符表名的反引号引用,以及default_db.前缀规避标准库名称冲突的完整方案,帮助你写出准确、可编译、可移植的 PRQL 查询。
from的基本用法:声明数据源
from的作用只有一个:指定一个数据源(data source)。在 PRQL 中,数据源通常对应数据库中的一张表:
from artists在 prqlc 标准库 中,from被定义为接受default_db.source表引用、返回该relation的转换函数:
let from = func `default_db.source` <relation> -> <relation> source可以看到,from的参数被限定为default_db命名空间下的表引用(<relation>类型),返回值即该关系本身。这正是 PRQL 把数据源当作普通关系(relation)对待的体现——from之后可以无缝接上select、filter、derive等任何标准库转换。
from是查询的必要起点
从编译器实现看,from不只是惯例,而是强制要求。在 lowering.rs 中,当存在用户声明但没有以from开头的管道时,编译器会直接报错:
PRQL queries must begin with 'from' A query must start with a 'from' statement to define the main pipeline因此,任何完整的 PRQL 查询都应以from定义主管道作为第一行,这一点在 集成测试 中大量体现,例如from tracks、from invoices、from genres等。
使用别名:赋值表达式
数据源表名不一定要与后续引用完全一致,可以用赋值表达式(assign expression)为表引入别名:
from e = employees select e.first_name别名在管道后续步骤中作为表限定符使用,能够消解列名歧义,让查询更清晰。集成测试中同样广泛采用这一写法,例如 group_sort.prql 中的from a=albums,以及 invoice_totals.prql 中的from i=invoices——后续步骤通过i.前缀引用该表的列。
需要说明的是,这种别名的引用机制建立在 标识符与this/that查找规则 之上:在join场景中,this指当前关系、that指另一张表;为from指定别名后,管道内即可用该别名精确限定列来源。
特殊字符与保留字:反引号引用
表名若包含空格或特殊字符,需要用反引号(backtick)包裹:
from `artist tracks`这与 PRQL 的标识符规则一脉相承。标识符与关键字文档 明确规定:标识符只能包含字母数字与下划线、不能以数字开头;要使用其他字符,就用反引号包围。编译到 SQL 时,这些标识符会按目标方言的规则进行引用和转义。
反引号引用同样适用于文件路径等非传统表名场景。在 read-files.md 中,DuckDB 允许直接在FROM子句写文件名,PRQL 中同样需要反引号:
from `artists.parquet`此外,PRQL 的保留字(如case、type、enum、func、module等)也都可以用反引号当作列名或变量名使用,例如`case`,其完整列表见 keywords.md。
与标准库函数重名:default_db.前缀
当表名恰好与标准库中的某个函数同名时,直接写from group会让编译器把group解析成标准库函数而非表名。此时可用default_db.前缀显式指明表属于默认数据库:
default_db.group # in place of `from group` take 1官方文档也坦承这是一个略显笨拙的临时方案(awkward workaround),其原因是from函数的签名限定为`default_db.source`——前缀default_db.正是为了让表引用显式落在default_db命名空间内,从而与std命名空间下的函数名区分开。这一点在标准库定义中可以得到印证:转换函数全部位于std命名空间(std.from与from等价),而表引用则归属于default_db命名空间。
在使用该语法时,管道起点不再是以from开头的语句,而是以default_db.table_name开头的表引用表达式,后续步骤(如take 1)仍照常串联。若后续官方解决该问题(对应 issue #3271),这一写法可能会被更优雅的语法取代,届时请以新版本文档为准。
进阶:多层级数据库与 Schema 前缀
from还支持带 schema 与数据库名的完整限定标识符。根据 标识符与关键字文档,可以写成:
from my_database.chinook.albums但需要注意:tracks、public.tracks、my_database.public.tracks会被编译器视为彼此独立的表定义,因此在同一查询中要避免混用不同层级的前缀,以免产生意外行为。
from在编译链路中的位置
从源码结构看,from的解析与处理贯穿 PRQL 编译链路的多个阶段:
- 词法/语法层:
from作为转换(transform)被识别。在 CLI 的语法高亮模块 highlight.rs 中,from被列为高亮关键字。 - 语义层:经解析后,管道必须在语义阶段以
from(或default_db.表引用)起始,否则 lowering.rs 报出E0001错误。 - SQL 生成层:在 keywords.rs 中,
from被确认为各 SQL 方言(Generic 等)的保留关键字,最终对应生成 SQL 的FROM子句。
换言之,你在 PRQL 中写的from最终会被编译器映射为 SQL 的FROM,而整个查询管道则围绕该数据源逐级构建。
总结
from虽然语法简单,却是 PRQL 每个查询的强制入口:
- 基础用法
from table直接声明数据源; from alias = table引入别名供管道后续引用;- 含空格或特殊字符的表名使用反引号
`table name`; - 与标准库函数重名的表名使用
default_db.group显式限定; - 支持
database.schema.table多级限定,但各层级写法被视为不同表。
若希望进一步了解关系数据的其他来源,可继续阅读 临时关系字面量(数组) 与 文件读取函数(DuckDB);关于prql target:等查询头配置,可参考 Target 与版本。
【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址: https://gitcode.com/gh_mirrors/pr/prql
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考