CREATE EXTERNAL TABLE¶
在当前/指定的架构中创建新的外部表或替换现有的外部表。查询时,外部表会从指定外部暂存区中包含一个或多个文件的集合中读取数据,并在单个 VARIANT 列中输出数据。
可以定义其他列,每个列定义由以下元素组成:名称、数据类型,以及(可选)列是否需要值 (NOT NULL) 或是否有任何参照完整性约束(主键、外键等)。有关更多信息,请参阅使用说明。
语法¶
-- Partitions computed from expressions
CREATE [ OR REPLACE ] EXTERNAL TABLE [IF NOT EXISTS]
<table_name>
( [ <col_name> <col_type> AS <expr> | <part_col_name> <col_type> AS <part_expr> ]
[ inlineConstraint ]
[ , <col_name> <col_type> AS <expr> | <part_col_name> <col_type> AS <part_expr> ... ]
[ , ... ] )
cloudProviderParams
[ PARTITION BY ( <part_col_name> [, <part_col_name> ... ] ) ]
[ WITH ] LOCATION = externalStage
[ REFRESH_ON_CREATE = { TRUE | FALSE } ]
[ AUTO_REFRESH = { TRUE | FALSE } ]
[ PATTERN = '<regex_pattern>' ]
FILE_FORMAT = ( { FORMAT_NAME = '<file_format_name>' | TYPE = { CSV | JSON | AVRO | ORC | PARQUET } [ formatTypeOptions ] } )
[ AWS_SNS_TOPIC = '<string>' ]
[ COPY GRANTS ]
[ COMMENT = '<string_literal>' ]
[ [ WITH ] ROW ACCESS POLICY <policy_name> ON (VALUE) ]
[ [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
-- Partitions added and removed manually
CREATE [ OR REPLACE ] EXTERNAL TABLE [IF NOT EXISTS]
<table_name>
( [ <col_name> <col_type> AS <expr> | <part_col_name> <col_type> AS <part_expr> ]
[ inlineConstraint ]
[ , <col_name> <col_type> AS <expr> | <part_col_name> <col_type> AS <part_expr> ... ]
[ , ... ] )
cloudProviderParams
[ PARTITION BY ( <part_col_name> [, <part_col_name> ... ] ) ]
[ WITH ] LOCATION = externalStage
PARTITION_TYPE = USER_SPECIFIED
FILE_FORMAT = ( { FORMAT_NAME = '<file_format_name>' | TYPE = { CSV | JSON | AVRO | ORC | PARQUET } [ formatTypeOptions ] } )
[ COPY GRANTS ]
[ COMMENT = '<string_literal>' ]
[ [ WITH ] ROW ACCESS POLICY <policy_name> ON (VALUE) ]
[ [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
-- Delta Lake
CREATE [ OR REPLACE ] EXTERNAL TABLE [IF NOT EXISTS]
<table_name>
( [ <col_name> <col_type> AS <expr> | <part_col_name> <col_type> AS <part_expr> ]
[ inlineConstraint ]
[ , <col_name> <col_type> AS <expr> | <part_col_name> <col_type> AS <part_expr> ... ]
[ , ... ] )
cloudProviderParams
[ PARTITION BY ( <part_col_name> [, <part_col_name> ... ] ) ]
[ WITH ] LOCATION = externalStage
PARTITION_TYPE = USER_SPECIFIED
FILE_FORMAT = ( { FORMAT_NAME = '<file_format_name>' | TYPE = { CSV | JSON | AVRO | ORC | PARQUET } [ formatTypeOptions ] } )
[ TABLE_FORMAT = DELTA ]
[ COPY GRANTS ]
[ COMMENT = '<string_literal>' ]
[ [ WITH ] ROW ACCESS POLICY <policy_name> ON (VALUE) ]
[ [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
其中:
inlineConstraint ::= [ NOT NULL ] [ CONSTRAINT <constraint_name> ] { UNIQUE | PRIMARY KEY | [ FOREIGN KEY ] REFERENCES <ref_table_name> [ ( <ref_col_name> [ , <ref_col_name> ] ) ] } [ <constraint_properties> ]有关其他内联约束的详细信息,请参阅 CREATE | ALTER TABLE ... CONSTRAINT。
cloudProviderParams (for Google Cloud Storage) ::= [ INTEGRATION = '<integration_name>' ] cloudProviderParams (for Microsoft Azure) ::= [ INTEGRATION = '<integration_name>' ]externalStage ::= @[<namespace>.]<ext_stage_name>[/<path>]formatTypeOptions ::= -- If FILE_FORMAT = ( TYPE = CSV ... ) COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | NONE RECORD_DELIMITER = '<character>' | NONE FIELD_DELIMITER = '<character>' | NONE SKIP_HEADER = <integer> SKIP_BLANK_LINES = TRUE | FALSE ESCAPE_UNENCLOSED_FIELD = '<character>' | NONE TRIM_SPACE = TRUE | FALSE FIELD_OPTIONALLY_ENCLOSED_BY = '<character>' | NONE NULL_IF = ( '<string1>' [ , '<string2>' , ... ] ) EMPTY_FIELD_AS_NULL = TRUE | FALSE ENCODING = '<string>' -- If FILE_FORMAT = ( TYPE = JSON ... ) COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | NONE ALLOW_DUPLICATE = TRUE | FALSE STRIP_OUTER_ARRAY = TRUE | FALSE STRIP_NULL_VALUES = TRUE | FALSE REPLACE_INVALID_CHARACTERS = TRUE | FALSE -- If FILE_FORMAT = ( TYPE = AVRO ... ) COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | NONE REPLACE_INVALID_CHARACTERS = TRUE | FALSE -- If FILE_FORMAT = ( TYPE = ORC ... ) TRIM_SPACE = TRUE | FALSE REPLACE_INVALID_CHARACTERS = TRUE | FALSE NULL_IF = ( '<string>' [ , '<string>' ... ] -- If FILE_FORMAT = ( TYPE = PARQUET ... ) COMPRESSION = AUTO | SNAPPY | NONE BINARY_AS_TEXT = TRUE | FALSE REPLACE_INVALID_CHARACTERS = TRUE | FALSE
变体语法¶
CREATE EXTERNAL TABLE ...USING TEMPLATE¶
创建一个新的外部表,其列定义派生自一组包含半结构化数据的暂存文件。此功能支持 Apache Parquet、Apache Avro、ORC、JSON 和 CSV 文件。对 CSV 和 JSON 文件的支持目前为预览版。
CREATE [ OR REPLACE ] EXTERNAL TABLE <table_name> [ COPY GRANTS ] USING TEMPLATE <query> [ ... ]
备注
如果语句要替换同名的现有表,则从要替换的表中复制授权。如果没有该名称的现有表,则从要克隆的源表中复制授权。
有关 COPY GRANTS 的更多详细信息,请参阅本文档中的 COPY GRANTS。
必填参数¶
table_name
指定表的标识符(即名称)的字符串;对于在其中创建表的架构必须是唯一的。
此外,标识符必须以字母字符开头,且不能包含空格或特殊字符,除非整个标识符字符串放在双引号内(例如,
"My object"
)。放在双引号内的标识符也区分大小写。有关更多详细信息,请参阅 标识符要求。
[ WITH ] LOCATION =
指定用于暂存包含要读取数据的文件的外部暂存区和可选路径:
@[namespace.]ext_stage_name[/path]
文件位于指定的命名外部暂存区。
既不支持字符串字面量也不支持 SQL 变量。
其中:
namespace
是外部暂存区所在的数据库和/或架构,格式为database_name.schema_name
或schema_name
。如果数据库和架构当前正在用户会话中使用,则此参数为 选填;否则,为必填。path
是云存储位置中文件(即文件的名称以通用字符串开头)的可选路径(区分大小写),用于限制要加载的文件集。不同的云存储服务也可以将路径称为 前缀 或 文件夹。外部表将此路径追加到暂存区定义中指定的任何路径。要查看暂存区定义,请执行
DESC STAGE stage_name
并检查url
属性值。例如,如果暂存 URL 包含路径a
,外部表位置包含路径b
,则外部表将读取暂存在stage/a/b
中的文件。请注意,
[ WITH ] LOCATION
值 不能 引用特定的文件名。若要将外部表指向单个暂存文件,请使用PATTERN
参数。
FILE_FORMAT = ( FORMAT_NAME = 'file_format_name' )
或 .FILE_FORMAT = ( TYPE = CSV | JSON | AVRO | ORC | PARQUET [ ... ] )
指定文件格式的字符串(常量):
FORMAT_NAME = file_format_name
指定描述要扫描的暂存数据文件的现有命名文件格式。命名的文件格式决定数据文件的格式类型(CSV、JSON 等)和其他任何格式选项。
TYPE = CSV | JSON | AVRO | ORC | PARQUET [ ... ]
指定查询外部表时要扫描的暂存数据文件的格式类型。
如果指定了文件格式类型,则可以指定其他特定于格式的选项。有关更多详细信息,请参阅 :ref:` 格式类型选项 <label-create_ext_table_formattypeoptions>` (本主题内容)。
文件格式选项可以在外部表级别或暂存区级别进行配置。在外部表级别指定的任何设置都优先。任何未在任一级别指定的设置都假定为默认值。
默认:
TYPE = CSV
。重要
外部表 不 继承暂存区定义中的文件格式(如果有)。必须 使用 FILE_FORMAT 参数为外部表显式指定任何文件格式选项。
备注
FORMAT_NAME
和TYPE
是互斥的;为了避免出现意外行为,在创建外部表时只应指定其中一个。
可选参数¶
col_name
指定列标识符(即名称)的字符串。表标识符的所有要求也适用于列标识符。
有关更多详细信息,请参阅 标识符要求。
col_type
指定列的数据类型的字符串(常量)。数据类型必须与列的
expr
结果匹配。有关可为表列指定的数据类型的详细信息,请参阅 SQL 数据类型参考。
expr
指定列的表达式的字符串。查询时,该列将返回从此表达式派生的结果。
外部表列是使用显式表达式定义的虚拟列。使用 VALUE 列和/或 METADATA$FILENAME 伪列将虚拟列添加为表达式:
- VALUE:
表示外部文件中单个行的 VARIANT 类型列。
- CSV:
列 VALUE 将每一行构建为一个对象,其元素由列位置(即
{c1: <column_1_value>, c2: <column_2_value>, c3: <column_1_value> ...}
)标识。例如,添加一个名为
mycol
的 VARCHAR,该列引用暂存 CSV 文件中的第一列:mycol varchar as (value:c1::varchar)
- 半结构化数据:
将元素名称和值放在双引号内。使用点表示法遍历 VALUE 列中的路径。
例如,假设以下内容表示暂存文件中的单行半结构化数据:
{ "a":"1", "b": { "c":"2", "d":"3" } }
例如,添加一个名为
mycol
的 VARCHAR 列,该列引用暂存文件中的嵌套重复c
元素:mycol varchar as (value:"b"."c"::varchar)
- METADATA$FILENAME:
一个伪列,标识外部表中包含的每个暂存数据文件的名称,包括其在暂存区中的路径。有关示例,请参阅 ` 从分区列表达式自动添加的分区 `_ (本主题内容)。
CONSTRAINT ...
为表中的指定列定义内联或外联约束的字符串。
有关语法的详细信息,请参阅 CREATE | ALTER TABLE ... CONSTRAINT。有关约束条件的更多信息,请参阅 约束。
REFRESH_ON_CREATE = TRUE | FALSE
指定是否在创建外部表后立即自动刷新一次外部表元数据。刷新外部表元数据会将元数据与指定暂存区路径中的当前数据文件列表同步。元数据需要执行此操作才能在
[ WITH ] LOCATION =
设置中指定的命名外部暂存区中注册任何 现有 数据文件。TRUE
Snowflake 会在创建外部表元数据后自动刷新一次。
备注
如果指定位置包含接近 100 万或更多的文件,我们建议您设置
REFRESH_ON_CREATE = FALSE
。创建外部表后,通过执行 ALTER EXTERNAL TABLE ... REFRESH 语句以增量方式刷新元数据 – 这些语句指定位置中的子路径(即刷新时要包含的文件子集)– 直到元数据包含该位置中的所有文件。FALSE
Snowflake 不会自动刷新外部表元数据。要注册暂存区中的任何现有数据文件,必须使用 ALTER EXTERNAL TABLE ... REFRESH 手动刷新一次外部表元数据。
默认:
TRUE
AUTO_REFRESH = TRUE | FALSE
指定当 新的或更新的 数据文件在
[ WITH ] LOCATION =
设置中指定的命名外部暂存区中可用时,Snowflake 是否应允许触发外部表元数据的自动刷新。备注
当分区由对象所有者手动添加时(即当
PARTITION_TYPE = USER_SPECIFIED
时),分区的外部表 不 支持将此参数设置为 TRUE。如果外部表引用了存储在 :doc:` 与 S3 兼容的外部暂存区 </user-guide/data-load-s3-compatible-storage>` 上的数据文件,则这些表 :emph:` 不 ` 支持将此参数设置为 TRUE。您必须通过执行 :doc:` ALTER EXTERNAL TABLE ...REFRESH </sql-reference/sql/alter-external-table>` 命令来执行完全刷新。
必须 为存储位置配置事件通知,以便在可将新的或更新的数据读入外部表元数据时通知 Snowflake。有关更多信息,请参阅云存储服务的说明:
- Amazon S3:
- Google Cloud Storage:
- Microsoft Azure:
创建外部表时,其元数据会自动刷新一次,除非
REFRESH_ON_CREATE = FALSE
。
TRUE
Snowflake 支持触发外部表元数据的自动刷新。
FALSE
Snowflake 不支持触发外部表元数据的自动刷新。您必须使用 ALTER EXTERNAL TABLE ... REFRESH 定期手动刷新外部表元数据,以使元数据与暂存区路径中的当前文件列表同步。
默认:
TRUE
PATTERN = 'regex_pattern'
正则表达式模式字符串放在单引号内,可指定外部暂存区上要匹配的文件名和/或路径。
小技巧
为了获得最佳性能,请尽量避免应用对大量文件进行筛选的模式。
AWS_SNS_TOPIC = 'string'
:emph:` 仅在使用 Amazon Simple Notification Service (SNS) 为 Amazon S3 暂存区配置 AUTO_REFRESH 时需要。 指定 S3 桶中 SNS 主题的 Amazon Resource Name (ARN)。CREATE EXTERNAL TABLE 语句将 Amazon Simple Queue Service (SQS) 队列订阅至指定的 SNS 主题。通过 SNS 主题的事件通知触发元数据刷新。有关更多信息,请参阅 :doc:/user-guide/tables-external-s3` 。
TABLE_FORMAT = DELTA
将外部表标识为引用云存储位置的 Delta Lake。支持 Amazon S3、Google Cloud Storage 或 Microsoft Azure 云存储中的 Delta Lake。
备注
所有账户都可以使用此 :doc:` 预览版功能 </release-notes/preview-features>`。
设置此参数后,外部表将扫描
[ WITH ] LOCATION
位置中的 Delta Lake 事务日志文件。Delta 日志文件的名称为_delta_log/00000000000000000000.json
、_delta_log/00000000000000000010.checkpoint.parquet
等。刷新外部表的元数据时,Snowflake 将解析 Delta Lake 事务日志并确定哪些 Parquet 文件是当前文件。在后台,刷新会执行文件添加和移除操作,以保持外部表元数据同步。
备注
[ WITH ] LOCATION =
中指定的外部暂存区和可选路径必须仅包含 单个 Delta Lake 表的数据文件和元数据。也就是说,指定的存储位置只能包含一个__delta_log
目录。云存储中 DDL 操作触发的事件通知顺序不受保证。因此,自动刷新功能不适用于引用 Delta Lake 文件的外部表。
REFRESH_ON_CREATE
和AUTO_REFRESH
都必须设置为 FALSE。定期执行 ALTER EXTERNAL TABLE ... REFRESH 语句来注册任何添加或移除的文件。
FILE_FORMAT
值必须将 Parquet 指定为文件类型。为了获得最佳性能,我们建议为外部表定义分区列。
引用 Delta Lake 时,不支持以下参数:
AWS_SNS_TOPIC = 'string'
PATTERN = 'regex_pattern'
COPY GRANTS
指定当使用 CREATE OR REPLACE TABLE 变体重新创建外部表时,保留原始表的访问权限。该参数将现有表中 除 OWNERSHIP 以外的所有权限复制到新表中。默认情况下,执行 CREATE EXTERNAL TABLE 命令的角色拥有新的外部表。
备注
复制授权的操作在 CREATE EXTERNAL TABLE 命令中会以原子方式发生(即在同一事务中)。
COMMENT = 'string_literal'
为外部表指定注释的字符串(字面量)。
默认:无值
ROW ACCESS POLICY <policy_name> ON (VALUE)
指定要在表上设置的 行访问策略。
将行访问策略应用于外部表时指定 VALUE 列。
TAG ( tag_name = 'tag_value' [ , tag_name = 'tag_value' , ... ] )
指定 标签 名称和标签字符串值。
标签值始终为字符串,标签值的最大字符数为 256。
有关在语句中指定标签的信息,请参阅 对象和列的标签配额。
分区参数¶
使用这些参数对外部表进行分区。
part_col_name col_type AS part_expr
定义外部表中的一个或多个分区列。
分区列定义的格式会有所不同,具体取决于分区是从每个分区列中的表达式自动计算和添加分区,还是手动添加分区。
- 从表达式添加:
分区列必须计算为解析 METADATA$FILENAME 伪列中的路径和/或文件名信息的表达式。分区列通过修剪不需要扫描的数据文件(即对外部表进行分区)来优化查询性能。分区由与分区列表达式中的路径和/或文件名匹配的所有数据文件组成。
part_col_name
指定分区列标识符(即名称)的字符串。表标识符的所有要求也适用于列标识符。
col_type
指定列的数据类型的字符串(常量)。数据类型必须与列的
part_expr
结果匹配。part_expr
指定列的表达式的字符串。表达式必须包含 METADATA$FILENAME 伪列。
外部表目前支持分区表达式中的以下函数子集:
支持的函数列表:
=
、<>
、>
、>=
、<
、<=
||
+
、-
-
(负号)*
AND
、OR
NOT
- 手动添加:
必需: 还要将
PARTITION_TYPE
参数值设置为USER_SPECIFIED
。分区列定义是解析内部(隐藏)METADATA$EXTERNAL_TABLE_PARTITION 列中的列元数据的表达式。从本质上讲,该定义仅定义列的数据类型。分区列定义的格式如下:
part_col_name col_type AS ( PARSE_JSON (METADATA$EXTERNALTABLE_PARTITION):part_col_name::data_type )
例如,假设列
col1
、col2
和col3
分别包含 varchar、number 和 timestamp(时区)数据:col1 varchar as (parse_json(metadata$external_table_partition):col1::varchar), col2 number as (parse_json(metadata$external_table_partition):col2::number), col3 timestamp_tz as (parse_json(metadata$external_table_partition):col3::timestamp_tz)
为表定义任何分区列后,使用 PARTITION BY 子句标识这些列。
备注
用户指定的分区列名的最大长度为 32 个字符。
PARTITION_TYPE = USER_SPECIFIED
将外部表的分区类型定义为 user-defined。外部表的所有者(即对外部表拥有 OWNERSHIP 权限的角色)必须通过执行 ALTER EXTERNAL TABLE ...ADD PARTITION 语句。
如果在评估分区列中的表达式时自动将分区添加到外部表元数据中,则 :emph:` 不要 ` 设置此参数。
[ PARTITION BY ( part_col_name [, part_col_name ... ] ) ]
指定要为外部表评估的任何分区列。
- 用途:
查询外部表时,在 WHERE 子句中包含一个或多个分区列,例如:
... WHERE part_col_name = 'filter_value'
Snowflake 筛选分区列以限制要扫描的数据文件集。请注意,这些文件中的所有行都会进行扫描。如果 WHERE 子句包含非分区列,则在筛选完数据文件 后 会对这些筛选器进行评估。
一种常见的做法是根据时间增量对数据文件进行分区;或者,如果数据文件是从多个源暂存的,则按数据源标识符和日期或时间戳进行分区。
云提供商参数 (cloudProviderParams
)¶
Google Cloud Storage
INTEGRATION = integration_name
指定用于使用 Google Pub/Sub 事件通知自动刷新外部表元数据的通知集成的名称。通知集成是一个 Snowflake 对象,它在 Snowflake 和第三方云消息队列服务之间提供一个接口。
此参数是启用外部表自动刷新操作所必需的。有关配置自动刷新功能的说明,请参阅 自动刷新 Google Cloud Storage 的外部表。
Microsoft Azure
INTEGRATION = integration_name
指定用于使用 Azure 事件网格通知自动刷新外部表元数据的通知集成的名称。通知集成是一个 Snowflake 对象,它在 Snowflake 和第三方云消息队列服务之间提供一个接口。
此参数是启用外部表自动刷新操作所必需的。有关配置自动刷新功能的说明,请参阅 自动刷新 Azure Blob 存储的外部表。
格式类型选项 (formatTypeOptions
)¶
格式类型选项用于 :doc:` 将数据加载到 </guides-overview-loading-data>` 中,以及 :doc:` 从 </user-guide/data-unload-overview>` 表中卸载数据。
根据指定的文件格式类型 (FILE_FORMAT = ( TYPE = ... )
),可以包含以下一个或多个特定于格式的选项(用空格、逗号或换行符分隔):
TYPE = CSV¶
COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | NONE
为要查询的数据文件指定当前压缩算法的字符串(常量)。Snowflake 使用此选项来检测 已压缩 的数据文件是如何压缩的,以便提取文件中的压缩数据进行查询。
支持的值
备注
AUTO
压缩算法会自动检测,但 Brotli 压缩文件除外(目前无法自动检测)。如果查询 Brotli 压缩文件,请显式使用
BROTLI
而不是AUTO
。GZIP
BZ2
BROTLI
查询 Brotli 压缩文件时必须指定此值。
ZSTD
支持 Zstandard v0.8(及更高版本)。
DEFLATE
使用 Deflate 压缩的文件(带有 zlib 标头、RFC1950)。
RAW_DEFLATE
使用 Raw Deflate 压缩的文件(无标头、RFC1951)。
NONE
数据文件尚未压缩。
RECORD_DELIMITER = 'character' | NONE
用于分隔输入文件中记录的一个或多个字符。接受常见的转义序列或以下单字节或多字节字符:
- 单字节字符:
八进制值(以
\\
为前缀)或十六进制值(以0x
或\x
为前缀)。例如,对于由重音符号 (^
) 字符分隔的记录,请指定八进制 (\\136
) 或十六进制 (0x5e
) 值。- 多字节字符:
十六进制值(前缀为
\x
)。例如,对于由分 (¢
) 字符分隔的记录,请指定十六进制 (\xC2\xA2
) 值。RECORD_DELIMITER 或 FIELD_DELIMITER 分隔符不能是其他文件格式选项(例如
FIELD_DELIMITER = 'aa' RECORD_DELIMITER = 'aabb'
)的分隔符的子字符串。
指定的分隔符必须是有效的 UTF-8 字符,而不是随机的字节序列。另请注意,分隔符限制为最多 20 个字符。
也接受
NONE
的值。默认值:换行符。请注意,“换行符”是合乎逻辑的,因而
\r\n
可以理解为 Windows 平台上文件的换行符。FIELD_DELIMITER = 'character' | NONE
一个或多个单字节或多字节字符,用于分隔输入文件中的字段。接受常见的转义序列或以下单字节或多字节字符:
- 单字节字符:
八进制值(以
\\
为前缀)或十六进制值(以0x
或\x
为前缀)。例如,对于由重音符号 (^
) 字符分隔的记录,请指定八进制 (\\136
) 或十六进制 (0x5e
) 值。- 多字节字符:
十六进制值(前缀为
\x
)。例如,对于由分 (¢
) 字符分隔的记录,请指定十六进制 (\xC2\xA2
) 值。RECORD_DELIMITER 或 FIELD_DELIMITER 分隔符不能是其他文件格式选项(例如
FIELD_DELIMITER = 'aa' RECORD_DELIMITER = 'aabb'
)的分隔符的子字符串。备注
对于非 ASCII 字符,必须使用十六进制字节序列值来获取确定性行为。
指定的分隔符必须是有效的 UTF-8 字符,而不是随机的字节序列。另请注意,分隔符限制为最多 20 个字符。
也接受
NONE
的值。默认值:逗号 (
,
)SKIP_HEADER = integer
要跳过的文件开头的行数。
注意,SKIP_HEADER 不使用 RECORD_DELIMITER 或 FIELD_DELIMITER 值来决定标头行;相反,它会直接跳过文件中指定数量的以 CRLF(回车符、换行)分隔的行。然后,使用 RECORD_DELIMITER 和 FIELD_DELIMITER 确定要查询的数据行。
默认:
0
SKIP_BLANK_LINES = TRUE | FALSE
- 使用:
仅数据查询
- 定义:
布尔,指定是否跳过数据文件中遇到的任何空行;否则,空行将产生记录结束错误(默认行为)。
默认:
FALSE
ESCAPE_UNENCLOSED_FIELD = 'character' | NONE
仅用作未封闭字段值的转义字符的单字节字符串。转义字符对字符序列中的后续字符调用替代解释。您可以使用 ESCAPE 字符将数据中
FIELD_DELIMITER
或RECORD_DELIMITER
字符的实例解释为字面量。转义字符还可用于对数据中自身的实例进行转义。接受常见的转义序列、八进制值或十六进制值。
仅指定未封闭字段的转义字符。
备注
默认值为
\\
。如果数据文件中的行以反斜杠 (\
) 字符结尾,则此字符将转义为RECORD_DELIMITER
文件格式选项指定的换行符或回车符。因此,此行和下一行将作为单行数据进行处理。若要避免此问题,请将值设置为NONE
。此文件格式选项仅支持单字节字符。请注意,UTF-8 字符编码将高阶 ASCII 字符表示为多字节字符。如果数据文件使用 UTF-8 字符集进行编码,则不能将高阶 ASCII 字符指定为选项值。
此外,如果指定高阶 ASCII 字符,建议将文件格式选项设置为
ENCODING = 'string'
数据文件的字符编码,以确保正确解释该字符。
默认值:反斜杠 (
\\
)TRIM_SPACE = TRUE | FALSE
布尔,指定是否从字段中移除空格。
例如,如果您的外部数据库软件将字段放在引号中,但插入了前导空格,则 Snowflake 会读取前导空格而不是左引号字符作为字段的开头(即引号被解释为字段数据字符串的一部分)。将此选项设置为
TRUE
可在查询数据时移除不需要的空格。再举一个例子,如果字符串两边的引号两边有前导空格或尾随空格,则可以使用此选项移除周围的空格,并使用
FIELD_OPTIONALLY_ENCLOSED_BY
选项移除引号字符。请注意,引号 内 的任何空格都将保留。例如,假设FIELD_DELIMITER = '|'
和FIELD_OPTIONALLY_ENCLOSED_BY = '"'
:|"Hello world"| /* returned as */ >Hello world< |" Hello world "| /* returned as */ > Hello world < | "Hello world" | /* returned as */ >Hello world<
请注意,此示例中的括号不返回;它们用于划分返回字符串的开头和结尾。
默认:
FALSE
FIELD_OPTIONALLY_ENCLOSED_BY = 'character' | NONE
用于包围字符串的字符。值可以是
NONE
、单引号字符 ('
) 或双引号字符 ("
)。要使用单引号字符,请使用八进制或十六进制表示形式 (0x27
) 或双单引号转义 (''
)。默认:
NONE
NULL_IF = ( 'string1' [ , 'string2' , ... ] )
用于与 SQL NULL 相互转换的字符串:
查询数据时,Snowflake 会将返回数据中的这些值替换为 SQL NULL。若要指定多个字符串,请将字符串列表放在括号中,并使用逗号分隔每个值。
请注意,无论数据类型如何,Snowflake 都会将该值的所有实例转换为 NULL。例如,如果
2
指定为值,则转换为字符串或数字的所有2
实例。例如:
NULL_IF = ('\N', 'NULL', 'NUL', '')
请注意,此选项可以包含空字符串。
默认:
\\N
(即 NULL,假设ESCAPE_UNENCLOSED_FIELD
值为\\
)EMPTY_FIELD_AS_NULL = TRUE | FALSE
指定是否为输入文件中的空字段返回 SQL NULL,这些字段由两个连续的分隔符表示(例如
,,
)。如果设置为
FALSE
,Snowflake 会尝试将空字段转换为相应列类型。对于类型为 STRING 的列,将返回一个空字符串。对于其他列类型,查询将返回错误。默认:
TRUE
ENCODING = 'string'
用于指定查询数据时源数据字符集的字符串(常量)。
字符 集
ENCODING
值支持的语言
备注
Big5
BIG5
繁体中文
EUC-JP
EUCJP
日语
EUC-KR
EUCKR
韩语
GB18030
GB18030
中文
IBM420
IBM420
阿拉伯语
IBM424
IBM424
希伯来语
IBM949
IBM949
韩语
ISO-2022-CN
ISO2022CN
简体中文
ISO-2022-JP
ISO2022JP
日语
ISO-2022-KR
ISO2022KR
韩语
ISO-8859-1
ISO88591
丹麦语、荷兰语、英语、法语、德语、意大利语、挪威语、葡萄牙语、瑞典语
ISO-8859-2
ISO88592
捷克语、匈牙利语、波兰语、罗马尼亚语
ISO-8859-5
ISO88595
俄语
ISO-8859-6
ISO88596
阿拉伯语
ISO-8859-7
ISO88597
希腊语
ISO-8859-8
ISO88598
希伯来语
ISO-8859-9
ISO88599
土耳其语
ISO-8859-15
ISO885915
丹麦语、荷兰语、英语、法语、德语、意大利语、挪威语、葡萄牙语、瑞典语
与 ISO-8859-1 相同,但 8 个字符除外,包括欧元货币符号。
KOI8-R
KOI8R
俄语
Shift_JIS
SHIFTJIS
日语
UTF-8
UTF8
所有语言
要从分隔文件(CSV、TSV 等)加载数据,默认为 UTF-8。. . 要从所有其他支持的文件格式(JSON、Avro 等)加载数据以及卸载数据,UTF-8 是唯一支持的字符集。
UTF-16
UTF16
所有语言
UTF-16BE
UTF16BE
所有语言
UTF-16LE
UTF16LE
所有语言
UTF-32
UTF32
所有语言
UTF-32BE
UTF32BE
所有语言
UTF-32LE
UTF32LE
所有语言
windows-949
WINDOWS949
韩语
windows-1250
WINDOWS1250
捷克语、匈牙利语、波兰语、罗马尼亚语
windows-1251
WINDOWS1251
俄语
windows-1252
WINDOWS1252
丹麦语、荷兰语、英语、法语、德语、意大利语、挪威语、葡萄牙语、瑞典语
windows-1253
WINDOWS1253
希腊语
windows-1254
WINDOWS1254
土耳其语
windows-1255
WINDOWS1255
希伯来语
windows-1256
WINDOWS1256
阿拉伯语
默认:
UTF8
备注
Snowflake 将所有数据存储在 UTF-8 字符集中。数据将转换为 UTF-8。
TYPE = JSON¶
COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | NONE
为要返回的数据文件指定当前压缩算法的字符串(常量)。Snowflake 使用此选项来检测 已压缩 的数据文件是如何压缩的,以便提取文件中的压缩数据进行查询。
支持的值
备注
AUTO
压缩算法会自动检测,但 Brotli 压缩文件除外(目前无法自动检测)。如果查询 Brotli 压缩文件,请显式使用
BROTLI
而不是AUTO
。GZIP
BZ2
BROTLI
ZSTD
DEFLATE
使用 Deflate 压缩的文件(带有 zlib 标头、RFC1950)。
RAW_DEFLATE
使用 Raw Deflate 压缩的文件(无标头、RFC1951)。
NONE
指示文件尚未压缩。
默认:
AUTO
ALLOW_DUPLICATE = TRUE | FALSE
布尔,指定允许重复对象字段名称(仅保留最后一个)。
默认:
FALSE
STRIP_OUTER_ARRAY = TRUE | FALSE
布尔,指示 JSON 解析器移除外括号(即
[ ]
)。默认:
FALSE
STRIP_NULL_VALUES = TRUE | FALSE
布尔,指示 JSON 解析器移除包含
null
值的对象字段或数组元素。例如,当设置为TRUE
时,会发生以下变化:之前
之后
[null]
[]
[null,null,3]
[,,3]
{"a":null,"b":null,"c":123}
{"c":123}
{"a":[1,null,2],"b":{"x":null,"y":88}}
{"a":[1,,2],"b":{"y":88}}
默认:
FALSE
REPLACE_INVALID_CHARACTERS = TRUE | FALSE
布尔,指定是否将无效的 UTF-8 字符替换为 Unicode 替换字符 (
�
)。此选项执行一对一的字符替换。如果设置为
TRUE
,Snowflake 会将无效的 UTF-8 字符替换为 Unicode 替换字符。如果设置为
FALSE
,则加载操作在检测到无效的 UTF-8 字符编码时产生错误。默认:
FALSE
TYPE = AVRO¶
COMPRESSION = AUTO | GZIP | BZ2 | BROTLI | ZSTD | DEFLATE | RAW_DEFLATE | NONE
为要查询的数据文件指定当前压缩算法的字符串(常量)。Snowflake 使用此选项来检测 已压缩 的数据文件是如何压缩的,以便提取文件中的压缩数据进行查询。
支持的值
备注
AUTO
压缩算法会自动检测,但 Brotli 压缩文件除外(目前无法自动检测)。如果查询 Brotli 压缩文件,请显式使用
BROTLI
而不是AUTO
。GZIP
BZ2
BROTLI
ZSTD
DEFLATE
使用 Deflate 压缩的文件(带有 zlib 标头、RFC1950)。
RAW_DEFLATE
使用 Raw Deflate 压缩的文件(无标头、RFC1951)。
NONE
要查询的数据文件尚未压缩。
默认:
AUTO
。
备注
我们建议您使用默认 AUTO
选项,因为它将确定文件和编解码器压缩。指定压缩选项是指对文件进行压缩,而不是对块(编解码器)进行压缩。
REPLACE_INVALID_CHARACTERS = TRUE | FALSE
布尔,指定是否将无效的 UTF-8 字符替换为 Unicode 替换字符 (
�
)。此选项执行一对一的字符替换。如果设置为
TRUE
,Snowflake 会将无效的 UTF-8 字符替换为 Unicode 替换字符。如果设置为
FALSE
,则加载操作在检测到无效的 UTF-8 字符编码时产生错误。默认:
FALSE
TYPE = ORC¶
TRIM_SPACE = TRUE | FALSE
布尔,指定是否从字符串中移除前导和尾随空格。
例如,如果您的外部数据库软件将字段放在引号中,但插入了前导空格,则 Snowflake 会读取前导空格而不是左引号字符作为字段的开头(即引号被解释为字段数据字符串的一部分)。将此选项设置为
TRUE
可移除不需要的空格。此文件格式选项仅适用于以下操作:
查询暂存 ORC 数据文件中的对象值。
使用 MATCH_BY_COLUMN_NAME 复制选项查询单独列中的 ORC 数据。
通过在 COPY 语句中指定查询来查询单独列中的 ORC 数据(即 COPY 转换)。
默认:
FALSE
REPLACE_INVALID_CHARACTERS = TRUE | FALSE
布尔,指定是否将无效的 UTF-8 字符替换为 Unicode 替换字符 (
�
)。此选项执行一对一的字符替换。如果设置为
TRUE
,Snowflake 会将无效的 UTF-8 字符替换为 Unicode 替换字符。如果设置为
FALSE
,则加载操作在检测到无效的 UTF-8 字符编码时产生错误。默认:
FALSE
NULL_IF = ( 'string1' [ , 'string2' , ... ] )
用于与 SQL NULL 相互转换的字符串。Snowflake 用 SQL NULL 替换数据源中的这些字符串。若要指定多个字符串,请将字符串列表放在括号中,并使用逗号分隔每个值。
请注意,无论数据类型如何,Snowflake 都会将该值的所有实例转换为 NULL。例如,如果
2
指定为值,则转换为字符串或数字的所有2
实例。例如:
NULL_IF = ('\N', 'NULL', 'NUL', '')
请注意,此选项可以包含空字符串。
在暂存 ORC 数据文件中查询对象值时,会应用此文件格式选项。
默认:
\\N
(即 NULL,假设ESCAPE_UNENCLOSED_FIELD
值为\\
)
TYPE = PARQUET¶
COMPRESSION = AUTO | SNAPPY | NONE
指定 Parquet 文件中列的当前压缩算法的字符串(常量)。
支持的值
备注
AUTO
自动检测压缩算法。支持以下压缩算法:Brotli、gzip、Lempel-Ziv-Oberhumer (LZO)、LZ4、Snappy 或 Zstandard v0.8(及更高版本)。
SNAPPY
NONE
数据文件尚未压缩。
默认:
AUTO
BINARY_AS_TEXT = TRUE | FALSE
布尔,指定是否将未定义逻辑数据类型的列解释为 UTF-8 文本。当设置为
FALSE
时,Snowflake 会将这些列解释为二进制数据。默认:
TRUE
备注
Snowflake 建议您将 BINARY_AS_TEXT 设置为 FALSE 以避免任何潜在的转换问题。
REPLACE_INVALID_CHARACTERS = TRUE | FALSE
布尔,指定是否将无效的 UTF-8 字符替换为 Unicode 替换字符 (
�
)。此选项执行一对一的字符替换。如果设置为
TRUE
,Snowflake 会将无效的 UTF-8 字符替换为 Unicode 替换字符。如果设置为
FALSE
,则加载操作在检测到无效的 UTF-8 字符编码时产生错误。默认:
FALSE
访问控制要求¶
权限 |
对象 |
备注 |
---|---|---|
CREATE EXTERNAL TABLE |
架构 |
|
CREATE STAGE |
架构 |
如果创建新暂存区,则为必填项。 |
USAGE |
暂存区 |
如果引用现有暂存区,则为必填项。 |
USAGE |
文件格式 |
请注意,对架构中的对象进行操作还需要对父数据库和架构具有 USAGE 权限。
有关创建具有指定权限集的自定义角色的说明,请参阅 创建自定义角色。
使用说明¶
外部表仅支持外部(即 S3、Azure 或 GCS)暂存区;不支持内部(即 Snowflake)暂存区。
您不能访问存档云存储类别中保存的数据,这些数据需要恢复后才能检索。例如,这些存档存储类别包括 Amazon S3 Glacier Flexible Retrieval 或 Glacier Deep Archive 存储类别,或者 Microsoft Azure Archive Storage。
Snowflake 不会对外部表强制实施完整性约束。特别是,与普通表不同,Snowflake 不强制执行 NOT NULL 约束。
外部表包括以下元数据列:
METADATA$FILENAME:外部表中包含的每个暂存数据文件的名称。包括暂存数据文件的路径。
METADATA$FILE_ROW_NUMBER:暂存数据文件中每条记录的行号。
外部表不支持以下情况:
群集密钥
克隆
XML 格式的数据
外部表不支持 Time Travel。
有关将外部表与策略一起使用的详细信息,请参阅:
使用
OR REPLACE
等效于在现有外部表上使用 DROP EXTERNAL TABLE,然后创建具有相同名称的新外部表。CREATE OR REPLACE <object> 语句是原子的。也就是说,当对象被替换时,旧对象将被删除,新对象将在单个事务中创建。
这意味着与 CREATE OR REPLACE EXTERNAL TABLE 操作并发的任何查询都使用旧的或新的外部表版本。
关于元数据:
注意
客户应确保在使用 Snowflake 服务时,不会将个人数据(用户对象除外)、敏感数据、出口管制数据或其他受监管数据作为元数据输入。有关更多信息,请参阅 Snowflake 中的元数据字段。
创建外部表时,将行访问策略添加到外部表中,使用 POLICY_CONTEXT 函数模拟受行访问策略保护的外部表上的查询。
SELECT
*
始终会返回 VALUE 列,其中所有常规或半结构化数据都投射到变体行。
示例¶
从分区列表达式自动添加的分区¶
创建一个外部表,其中包含从分区列定义中的表达式计算的分区。
在以下示例中,数据文件按以下结构在云存储中组织:logs/YYYY/MM/DD/HH24
。例如:
logs/2018/08/05/0524/
logs/2018/08/27/1408/
为存储数据文件的存储位置创建一个名为
s1
的外部暂存区。有关更多信息,请参阅 CREATE STAGE。暂存区定义包括路径
/files/logs/
:Amazon S3
CREATE STAGE s1 URL='s3://mybucket/files/logs/' ... ;
Google Cloud Storage
CREATE STAGE s1 URL='gcs://mybucket/files/logs/' ... ;
Microsoft Azure
CREATE STAGE s1 URL='azure://mycontainer/files/logs/' ... ;
查询暂存数据中的 METADATA$FILENAME 伪列。使用结果来开发分区列:
SELECT metadata$filename FROM @s1/; +----------------------------------------+ | METADATA$FILENAME | |----------------------------------------| | files/logs/2018/08/05/0524/log.parquet | | files/logs/2018/08/27/1408/log.parquet | +----------------------------------------+
创建已分区的外部表。
分区列
date_part
使用 TO_DATE、DATE 将 METADATA$FILENAME 伪列中的YYYY/MM/DD
转换为日期。SQL 命令还将 Parquet 指定为文件格式类型。Amazon S3 和 Microsoft Azure 云存储的外部表包括由来自相应云消息传递服务的事件通知触发时自动刷新元数据所需的参数:
Amazon S3
CREATE EXTERNAL TABLE et1( date_part date AS TO_DATE(SPLIT_PART(metadata$filename, '/', 3) || '/' || SPLIT_PART(metadata$filename, '/', 4) || '/' || SPLIT_PART(metadata$filename, '/', 5), 'YYYY/MM/DD'), timestamp bigint AS (value:timestamp::bigint), col2 varchar AS (value:col2::varchar)) PARTITION BY (date_part) LOCATION=@s1/logs/ AUTO_REFRESH = true FILE_FORMAT = (TYPE = PARQUET) AWS_SNS_TOPIC = 'arn:aws:sns:us-west-2:001234567890:s3_mybucket';
Google Cloud Storage
CREATE EXTERNAL TABLE et1( date_part date AS TO_DATE(SPLIT_PART(metadata$filename, '/', 3) || '/' || SPLIT_PART(metadata$filename, '/', 4) || '/' || SPLIT_PART(metadata$filename, '/', 5), 'YYYY/MM/DD'), timestamp bigint AS (value:timestamp::bigint), col2 varchar AS (value:col2::varchar)) PARTITION BY (date_part) LOCATION=@s1/logs/ AUTO_REFRESH = true FILE_FORMAT = (TYPE = PARQUET);
Microsoft Azure
CREATE EXTERNAL TABLE et1( date_part date AS TO_DATE(SPLIT_PART(metadata$filename, '/', 3) || '/' || SPLIT_PART(metadata$filename, '/', 4) || '/' || SPLIT_PART(metadata$filename, '/', 5), 'YYYY/MM/DD'), timestamp bigint AS (value:timestamp::bigint), col2 varchar AS (value:col2::varchar)) PARTITION BY (date_part) INTEGRATION = 'MY_INT' LOCATION=@s1/logs/ AUTO_REFRESH = true FILE_FORMAT = (TYPE = PARQUET);
刷新外部表元数据:
ALTER EXTERNAL TABLE et1 REFRESH;
查询外部表时,使用 WHERE 子句按分区列筛选数据。Snowflake 仅扫描指定分区中符合筛选条件的文件:
SELECT timestamp, col2 FROM et1 WHERE date_part = to_date('08/05/2018');
手动添加的分区¶
使用用户定义的分区创建外部表(即分区由外部表所有者手动添加)。
为存储数据文件的存储位置创建一个名为
s2
的外部暂存区:暂存区定义包括路径
/files/logs/
:Amazon S3
CREATE STAGE s2 URL='s3://mybucket/files/logs/' ... ;
Google Cloud Storage
CREATE STAGE s2 URL='gcs://mybucket/files/logs/' ... ;
Microsoft Azure
CREATE STAGE s2 URL='azure://mycontainer/files/logs/' ... ;
创建已分区的外部表。外部表包括三个具有不同数据类型的分区列。
请注意,分区表达式中的列名区分大小写。以下规则适用:
分区列名 必须 为大写,除非列名放在双引号内。或者,在 SQL 表达式中使用 GET_IGNORE_CASE 而不是区分大小写的
:
字符。如果列名放在双引号内(例如 "Column1"),则分区列名也必须放在双引号内,并且与列名完全匹配。
三种云存储服务(Amazon S3、Google Cloud Storage 和 Microsoft Azure)的语法相同,因为外部表元数据不会刷新:
create external table et2( col1 date as (parse_json(metadata$external_table_partition):COL1::date), col2 varchar as (parse_json(metadata$external_table_partition):COL2::varchar), col3 number as (parse_json(metadata$external_table_partition):COL3::number)) partition by (col1,col2,col3) location=@s2/logs/ partition_type = user_specified file_format = (type = parquet);
为分区列添加分区:
ALTER EXTERNAL TABLE et2 ADD PARTITION(col1='2022-01-24', col2='a', col3='12') LOCATION '2022/01';
Snowflake 将分区添加到外部表的元数据中。该操作还会将指定位置的任何新数据文件添加到元数据中:
+---------------------------------------+----------------+-------------------------------+ | file | status | description | +---------------------------------------+----------------+-------------------------------+ | mycontainer/files/logs/2022/01/24.csv | REGISTERED_NEW | File registered successfully. | | mycontainer/files/logs/2022/01/25.csv | REGISTERED_NEW | File registered successfully. | +---------------------------------------+----------------+-------------------------------+
查询外部表时,使用 WHERE 子句按分区列筛选数据。此示例按记录在暂存数据文件中的存储顺序返回记录:
SELECT col1, col2, col3 FROM et1 WHERE col1 = TO_DATE('2022-01-24') AND col2 = 'a' ORDER BY METADATA$FILE_ROW_NUMBER;
引用 Delta Lake 中文件的外部表¶
创建一个名为 ext_twitter_feed
的分区外部表,该表引用 mystage
外部暂存区和 daily
路径中 Parquet 格式的 Delta Lake 文件。
分区列 date_part
使用 TO_DATE、DATE 将 METADATA$FILENAME 伪列中的 YYYY/MM/DD
转换为日期:
CREATE EXTERNAL TABLE ext_twitter_feed(
date_part date AS TO_DATE(SPLIT_PART(metadata$filename, '/', 3)
|| '/' || SPLIT_PART(metadata$filename, '/', 4)
|| '/' || SPLIT_PART(metadata$filename, '/', 5), 'YYYY/MM/DD'),
timestamp bigint AS (value:timestamp::bigint),
col2 varchar AS (value:col2::varchar))
PARTITION BY (date_part)
LOCATION=@mystage/daily/
REFRESH_ON_CREATE = FALSE
AUTO_REFRESH = FALSE
FILE_FORMAT = (TYPE = PARQUET)
TABLE_FORMAT = DELTA;
外部表上的物化视图¶
基于 ` 从分区列表达式自动添加的分区 `_ 中创建的外部表中列的子查询创建物化视图示例:
CREATE MATERIALIZED VIEW et1_mv
AS
SELECT col2 FROM et1;
有关此 SQL 命令的一般语法、用法说明和更多示例,请参阅 CREATE MATERIALIZED VIEW。
使用检测到的列定义创建的外部表¶
创建一个外部表,其中的列定义源自一组包含 Avro、Parquet 或 ORC 数据的暂存文件。
请注意,语句中引用的 mystage
暂存区和 my_parquet_format
文件格式必须已存在。一组文件必须已暂存在暂存区定义中引用的云存储位置中。
本例以 INFER_SCHEMA 主题中的一个示例为基础:
CREATE EXTERNAL TABLE mytable USING TEMPLATE ( SELECT ARRAY_AGG(OBJECT_CONSTRUCT(*)) FROM TABLE( INFER_SCHEMA( LOCATION=>'@mystage', FILE_FORMAT=>'my_parquet_format' ) ) ) LOCATION=@mystage FILE_FORMAT=my_parquet_format AUTO_REFRESH=false;
如果返回的结果大于 16 MB,则在 ARRAY_AGG(OBJECT_CONSTRUCT())
中使用 *
可能会导致错误。避免对较大的结果集使用 *
,而是仅将所需的列 COLUMN NAME
、TYPE
和 NULLABLE
用于查询,如以下示例所示。使用 ORDER_ID
时可以包含可选列 WITHIN GROUP (ORDER BY order_id)
。
CREATE EXTERNAL TABLE mytable USING TEMPLATE ( SELECT ARRAY_AGG(OBJECT_CONSTRUCT('COLUMN_NAME',COLUMN_NAME, 'TYPE',TYPE, 'NULLABLE', NULLABLE, 'EXPRESSION',EXPRESSION)) FROM TABLE( INFER_SCHEMA( LOCATION=>'@mystage', FILE_FORMAT=>'my_parquet_format' ) ) ) LOCATION=@mystage FILE_FORMAT=my_parquet_format AUTO_REFRESH=false;