Snowflake中如何查询暂存文件的所有列及对应列名
Snowflake查询暂存文件全列+真实列名实现方案
问题原因
直接对暂存区(stage)执行SELECT *触发SELECT with no columns报错,是因为Snowflake直接查询外部暂存文件时,默认不会自动解析文件内置的表头元数据,仅将每行识别为可按位置引用的文本行,只能通过$1、$2这类位置标识访问列,自然无法直接返回真实列名。
方案1:通用方案(支持所有文件格式,含CSV/TSV等纯文本格式)
用Snowflake原生的INFER_SCHEMA函数自动扫描文件解析表头和列数,无需手动追加$N列引用:
- 第一步:自动扫描暂存文件,解析全量列信息
-- 自动识别暂存文件的所有列名、类型、位置 SELECT COLUMN_NAME, TYPE, ORDER_ID FROM TABLE( INFER_SCHEMA( LOCATION=>'@my_stage/my_file_path', FILE_FORMAT=>'my_format', IGNORE_CASE=>TRUE ) );
返回结果中COLUMN_NAME就是文件的真实列名,ORDER_ID对应列的位置序号,无需手动数总列数。
- 第二步:基于解析出的schema创建临时外部表,直接查询即可返回带真实列名的全量数据
-- 创建临时外部表,自动映射所有列 CREATE OR REPLACE TEMPORARY EXTERNAL TABLE temp_staged_data USING TEMPLATE ( SELECT ARRAY_AGG(OBJECT_CONSTRUCT(*)) FROM TABLE( INFER_SCHEMA( LOCATION=>'@my_stage/my_file_path', FILE_FORMAT=>'my_format' ) ) ) LOCATION=@my_stage FILE_FORMAT=my_format PATTERN='my_file_path'; -- 直接查询返回所有列,列名与文件表头完全一致 SELECT * FROM temp_staged_data;
注意:如果查询的是CSV类带表头的纯文本文件,需要提前将对应FILE_FORMAT的SKIP_HEADER参数设为1,否则会把表头行识别为数据行,导致列解析错误。
方案2:简化方案(仅支持Parquet/ORC等自带元数据的文件格式)
如果暂存的是Parquet、ORC这类文件本身存储了schema元数据的格式,不需要建临时表,直接用$1:*语法即可展开所有列,自动返回真实列名:
SELECT METADATA$FILENAME AS source_file_name, -- 可选:返回数据所属的源文件名 $1:* -- 自动展开所有列,使用文件内置的列名作为返回字段名 FROM @my_stage (FILE_FORMAT=>'my_format',PATTERN=>'my_file_path');
多文件匹配场景下,INFER_SCHEMA会自动扫描所有匹配到的文件做schema合并,兼容列顺序、字段类型的差异,比手动追加$N列的方式稳定性更高。
内容的提问来源于stack exchange,提问作者user18466310
相关产品推荐
相关产品推荐

