SQL 数据类型:最大长度、输出和错误消息的变更(待定)¶
随着此行为变更,编译后的 SQL 表达式和一些错误消息的行为如下所示:
- 变更前:
在编译后的 SQL 表达式和错误消息中,Snowflake 明确指定了数据类型的长度(如
VARCHAR(16777216)
)。当加载大于 16 MB 的对象时,会返回与解析或处理大的字符串或文件相关的错误(如
100069 (22P02): Error parsing JSON: document is too large, max size 16777216 bytes
)。
- 变更后:
在编译后的 SQL 表达式和错误消息中,Snowflake 省略了数据类型的长度(如
VARCHAR
)。当加载大于 16 MB 的对象时,会返回与存储大型对象相关的错误(如
100082 (22000):超过最大 LOB 大小 (16777216),解析列的实际大小为 <actual_size>
)。
在过去,如果尝试在一个暂存区查询一个大于 16 MB(对于 BINARY、GEOMETRY 和 GEOGRAPHY 为 8 MB)的对象,则会发生错误。您现在可以读取和处理大小高达 128 MB 的对象。尽管您仍然无法在列中加载大于 16 MB 的对象或将它们输出到结果集中,但您可在一个暂存区上的文件中查询大小不超过 128 MB(对于 BINARY、GEOMETRY 和 GEOGRAPHY 为 64 MB)的对象,并在将对象存储到列中之前减小对象的大小。
有关更多信息,请参阅 加载前减小大于 16 MB 的对象的尺寸。
新的大小限制没有在 SQL 查询输出或元数据中显式公开。但是,您可以通过创建或读取更大的对象来隐式观察新增加的长度,但不存储它们。启用此功能会带来以下行为变更:
在列表达式、UDFs 和存储过程的 GET_DDL、SHOW 和 DESCRIBE 命令输出中,VARCHAR 和 BINARY 类型显示为无长度。
例如,会显示为
VARCHAR
,而不是VARCHAR(16777216)
。此变更仅适用于未在 DDL 语句中显式指定长度的新创建对象。此变更不适用于现有对象。之前因 :code:`maximum size exceeded`(或类似)错误而失败的一些语句现在将成功执行。
现在,只加载或创建但不存储或返回较大值的语句将成功执行。
一些之前因 :code:`maximum size exceeded`(或类似)错误而失败的语句将继续失败,但会出现不同的错误代码或消息。
新的错误代码和消息仍然与超过 16 MB 限制有关,但错误可能源自执行计划的不同部分。例如,
cannot load value
可能会变成cannot store value
或cannot output value
。
首次变更会影响所有客户。第二和第三次变更会影响那些试图加载或生成大于 16 MB 的对象的客户。
重要
我们强烈建议不要创建依赖于与大于 16 MB 的对象相关的错误消息的逻辑。实际上,您可以构建使用 BIT_LENGTH 函数来检查值大小的逻辑。
元数据的变更¶
有一些行为变更会影响以下类型的操作:
对于这些类型的操作,结果集中的元数据会发生变更。
备注
此列表并不详尽。
返回 UDFs 的元数据¶
对于使用 VARCHAR 或 BINARY 值作为输入或输出的新用户定义函数 (UDFs),在调用 GET_DDL 函数、运行 DESCRIBE FUNCTION 语句或查询 事件表 时,与 UDFs 相关的 DDL 语句的元数据变更会影响返回的输出。以下示例创建了一个 UDF:
CREATE OR REPLACE FUNCTION udf_varchar(g1 VARCHAR)
RETURNS VARCHAR
AS $$
'Hello' || g1
$$;
GET_DDL¶
调用 GET_DDL 函数所返回的元数据会发生如下更改:
SELECT GET_DDL('function', 'udf_varchar(VARCHAR)');
- 变更前的元数据:
CREATE OR REPLACE FUNCTION "UDF_VARCHAR"("G1" VARCHAR(16777216)) RETURNS VARCHAR(16777216) LANGUAGE SQL AS ' ''Hello'' || g1 ';
- 变更后的元数据:
CREATE OR REPLACE FUNCTION "UDF_VARCHAR"("G1" VARCHAR) RETURNS VARCHAR LANGUAGE SQL AS ' ''Hello'' || g1 ';
DESCRIBE FUNCTION¶
DESCRIBE FUNCTION 语句返回的元数据会发生如下更改:
DESCRIBE FUNCTION udf_varchar(VARCHAR);
- 变更前的元数据:
+-----------+-------------------+ | property | value | |-----------+-------------------| | signature | (G1 VARCHAR) | | returns | VARCHAR(16777216) | | language | SQL | | body | | | | 'Hello' || g1 | | | | +-----------+-------------------+
- 变更后的元数据:
+-----------+-------------------+ | property | value | |-----------+-------------------| | signature | (G1 VARCHAR) | | returns | VARCHAR | | language | SQL | | body | | | | 'Hello' || g1 | | | | +-----------+-------------------+
事件表¶
对于返回 VARCHAR 或 BINARY 值作为输出的新用户定义函数,事件表 的 RESOURCE_ATTRIBUTES 列中的 snow.executable.name
属性会发生如下更改:
- 变更前的元数据:
{ "db.user": "MYUSERNAME", "snow.database.id": 13, "snow.database.name": "MY_DB", "snow.executable.id": 197, "snow.executable.name": "UDF_VARCHAR(X VARCHAR):VARCHAR(16777216)", "snow.executable.type": "FUNCTION", "snow.owner.id": 2, "snow.owner.name": "MY_ROLE", "snow.query.id": "01ab0f07-0000-15c8-0000-0129000592c2", "snow.schema.id": 16, "snow.schema.name": "PUBLIC", "snow.session.id": 1275605667850, "snow.session.role.primary.id": 2, "snow.session.role.primary.name": "MY_ROLE", "snow.user.id": 25, "snow.warehouse.id": 5, "snow.warehouse.name": "MYWH", "telemetry.sdk.language": "python" }
- 变更后的元数据:
{ "db.user": "MYUSERNAME", "snow.database.id": 13, "snow.database.name": "MY_DB", "snow.executable.id": 197, "snow.executable.name": "UDF_VARCHAR(X VARCHAR):VARCHAR", "snow.executable.type": "FUNCTION", "snow.owner.id": 2, "snow.owner.name": "MY_ROLE", "snow.query.id": "01ab0f07-0000-15c8-0000-0129000592c2", "snow.schema.id": 16, "snow.schema.name": "PUBLIC", "snow.session.id": 1275605667850, "snow.session.role.primary.id": 2, "snow.session.role.primary.name": "MY_ROLE", "snow.user.id": 25, "snow.warehouse.id": 5, "snow.warehouse.name": "MYWH", "telemetry.sdk.language": "python" }
返回具有列表达式的表的元数据¶
对于在列表达式中使用 VARCHAR 或 BINARY 的新表,与这些列相关的 DDL 语句的元数据变更会影响调用 GET_DDL 函数时返回的输出。
以下示例创建一个具有列表达式的表。
CREATE OR REPLACE TABLE table_with_default(x INT, v TEXT DEFAULT x::VARCHAR);
调用 GET_DDL 函数所返回的元数据会发生如下更改:
SELECT GET_DDL('table', 'table_with_default');
- 变更前的元数据:
create or replace TABLE TABLE_WITH_DEFAULT ( | X NUMBER(38,0), V VARCHAR(16777216) DEFAULT CAST(TABLE_WITH_DEFAULT.X AS VARCHAR(16777216)) );
- 变更后的元数据:
create or replace TABLE TABLE_WITH_DEFAULT ( | X NUMBER(38,0), V VARCHAR(16777216) DEFAULT CAST(TABLE_WITH_DEFAULT.X AS VARCHAR) );
外部表¶
以下示例创建了一个外部表:
CREATE OR REPLACE EXTERNAL TABLE ext_table(
data_str VARCHAR AS (value:c1::TEXT))
LOCATION = @csv_stage
AUTO_REFRESH = false
FILE_FORMAT =(type = csv);
调用 GET_DDL 函数所返回的元数据会发生如下更改:
SELECT GET_DDL('table', 'ext_table');
- 变更前的元数据:
create or replace external table EXT_TABLE( DATA_STR VARCHAR(16777216) AS (CAST(GET(VALUE, 'c1') AS VARCHAR(16777216)))) location=@CSV_STAGE/ auto_refresh=false file_format=(TYPE=csv) ;
- 变更后的元数据:
create or replace external table EXT_TABLE( DATA_STR VARCHAR(16777216) AS (CAST(GET(VALUE, 'c1') AS VARCHAR))) location=@CSV_STAGE/ auto_refresh=false file_format=(TYPE=csv) ;
返回 SYSTEM$TYPEOF 的元数据¶
调用 SYSTEM$TYPEOF 函数所返回的元数据变更如下:
SELECT SYSTEM$TYPEOF(REPEAT('a',10));
- 变更前的元数据:
VARCHAR(16777216)[LOB]
- 变更后的元数据:
VARCHAR[LOB]
返回 SHOW COLUMNS 的元数据¶
此变更会同时影响现有表和新表。SHOW COLUMNS 语句所返回的元数据变更如下:
CREATE OR REPLACE TABLE t AS
SELECT TO_VARIANT('abc') AS col;
SHOW COLUMNS IN t;
- 变更前的元数据:
{ "type":"VARIANT", "length":16777216, "byteLength":16777216, "nullable":true, "fixed":false }
- 变更后的元数据:
{ "type":"VARIANT", "nullable":true, "fixed":false }
加载和处理大于 16 MB 的对象的变更¶
在尝试使用以下类型的操作加载或处理大于 16 MB 的对象时,有些行为变更会影响情况:
备注
此列表并不详尽。
通过扫描暂存区上的文件加载数据¶
当您尝试通过扫描暂存区上的文件来加载大于 16 MB 的数据时,将返回错误消息。
使用 CREATE TABLE AS SELECT 加载整个大型对象¶
当尝试使用 CREATE TABLE AS SELECT 语句来加载大于 16 MB(对于 VARCHAR、VARIANT、OBJECT 和 ARRAY)或大于 8 MB(对于 BINARY、GEOMETRY 或 GEOGRAPHY)的对象时,会出现不同的错误消息。错误取决于源的类型。在这种情况下,使用 INSERT INTO SELECT 语句时,也会出现同样的消息变更。
从一个 JSON 源加载整个大型对象¶
以下示例尝试使用 CREATE TABLE AS SELECT 从一个 JSON 源加载一个大于 16 MB 的整个对象:
CREATE OR REPLACE FILE FORMAT json_format TYPE = JSON;
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR) AS
SELECT $1::VARCHAR
FROM @lob_int_stage/driver_status.json.gz (FILE_FORMAT => 'json_format');
- 变更前的错误消息:
100069 (22P02): Error parsing JSON: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <actual_size>
从一个 XML 源加载一个完整的大型对象¶
以下示例尝试使用 CREATE TABLE AS SELECT 从一个 XML 源加载一个大于 16 MB 的整个对象:
CREATE or REPLACE FILE FORMAT xml_format TYPE = XML;
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR) AS
SELECT $1 AS XML
FROM @lob_int_stage/large_xml.xte (FILE_FORMAT => 'xml_format');
- 变更前的错误消息:
100100 (22P02): Error parsing XML: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100078 (22000): String '<string_preview>' is too long and would be truncated
使用 COPY INTO <table_name> ...FROM SELECT¶
当尝试使用 COPY INTO <table_name> ...FROM SELECT 语句来加载大于 16 MB(对于 VARCHAR、VARIANT、OBJECT 和 ARRAY)或大于 8 MB(对于 BINARY、GEOMETRY 或 GEOGRAPHY)的对象时,会出现不同的错误消息。错误取决于源的类型。
重要
如果尝试使用带有 ON_ERROR=CONTINUE
的 COPY INTO 命令加载包含大于 16 MB 对象的数据,并依赖于错误日志中写入的错误消息,则错误消息的变更可能会导致依赖于错误消息的逻辑出现问题。
从一个 JSON 源加载整个大型对象¶
以下示例尝试从一个 JSON 源加载一个大于 16 MB 的整个对象,方法是使用 COPY INTO <table_name> ...FROM SELECT:
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR);
COPY INTO table_varchar FROM (
SELECT $1::VARCHAR
FROM @lob_int_stage/driver_status.json.gz (FILE_FORMAT => 'json_format'));
- 变更前的错误消息:
100069 (22P02): Error parsing JSON: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <actual_size>
从一个 JSON 源加载大型嵌套对象¶
以下示例尝试在访问大型嵌套对象时加载 JSON 数据:
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR);
COPY INTO table_varchar FROM (
SELECT $1:"Driver_Status"
FROM @lob_int_stage/driver_status.json.gz (FILE_FORMAT => 'json_format'));
- 变更前的错误消息:
100069 (22P02): Max LOB size (16777216) exceeded, actual size of parsed column is <object_size>
- 变更后的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <actual_size>
从一个 XML 源加载一个完整的大型对象¶
以下示例尝试从一个 XML 源加载一个大于 16 MB 的整个对象,方法是使用 COPY INTO <table_name> ...FROM SELECT:
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR);
COPY INTO table_varchar FROM (
SELECT $1::VARCHAR AS lob_column
FROM @lob_int_stage/large_xml.xte (FILE_FORMAT => 'xml_format'));
- 变更前的错误消息:
100100 (22P02): Error parsing XML: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <object_size>
使用 COPY INTO <table_name> ...FROM <stage_or_location> 加载整个大型对象¶
当尝试使用 COPY INTO <table_name> ...FROM <stage_or_location> 语句来加载大于 16 MB(对于 VARCHAR、VARIANT、OBJECT 和 ARRAY)或大于 8 MB(对于 BINARY、GEOMETRY 或 GEOGRAPHY)的对象时,会出现不同的错误消息。错误取决于源的类型。
如果使用 COPY 命令来处理大型对象,即使将 ON_ERROR
参数设置为 CONTINUE
,查询也可能会失败。有关更多信息,请参阅 COPY 命令的使用说明。
重要
如果尝试使用带有 ON_ERROR=CONTINUE
的 COPY INTO 命令加载包含大于 16 MB 对象的数据,并依赖于错误日志中写入的错误消息,则错误消息的变更可能会导致依赖于消息的逻辑出现问题。
从一个 JSON 源加载整个大型对象¶
以下示例尝试从一个 JSON 源加载一个大于 16 MB 的整个对象,方法是使用 COPY INTO <table_name> ...FROM <stage_or_location>:
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR);
COPY INTO table_varchar (lob_column)
FROM @lob_int_stage/driver_status.json.gz
FILE_FORMAT = (FORMAT_NAME = json_format);
- 变更前的错误消息:
100069 (22P02): Error parsing JSON: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <actual_size>
从一个 XML 源加载一个完整的大型对象¶
以下示例尝试从一个 XML 源加载一个大于 16 MB 的整个对象,方法是使用 COPY INTO <table_name> ...FROM <stage_or_location>:
CREATE OR REPLACE TABLE table_varchar (lob_column VARCHAR);
COPY INTO table_varchar (lob_column)
FROM @lob_int_stage/large_xml.xte
FILE_FORMAT = (FORMAT_NAME = xml_format);
- 变更前的错误消息:
100100 (22P02): Error parsing XML: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <actual_size>
从一个源文件查询整个大型对象¶
由于当前结果集中不允许大于 16 MB 的对象,因此当您尝试从源文件中查询大于 16 MB(对于 VARCHAR、VARIANT、OBJECT 和 ARRAY)或大于 8 MB(对于 BINARY、GEOMETRY 或 GEOGRAPHY)的对象时,会出现不同的错误消息。错误取决于源的类型。
从一个 JSON 源查询整个大型对象¶
以下示例尝试从一个 JSON 源查询一个大于 16 MB 的整个对象:
SELECT $1
FROM @lob_int_stage/driver_status.json.gz (FILE_FORMAT => 'json_format');
- 变更前的错误消息:
100069 (22P02): Error parsing JSON: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): The data length in result column $1 is not supported by this version of the client. Actual length <actual_length> exceeds supported length of 16777216.
从一个 XML 源查询整个大型对象¶
以下示例尝试从一个 XML 源查询一个大于 16 MB 的整个对象:
SELECT $1 as lob_column
FROM @lob_int_stage/large_xml.xte (FILE_FORMAT => 'xml_format');
- 变更前的错误消息:
100100 (22P02): Error parsing XML: document is too large, max size 16777216 bytes
- 变更后的错误消息:
100082 (22000): The data length in result column $1 is not supported by this version of the client. Actual length <actual_length> exceeds supported length of 16777216.
从一个 CSV 源查询整个大型对象¶
以下示例尝试从一个 CSV 源查询一个大于 16 MB 的整个对象:
SELECT $1
FROM @lob_int_stage/driver_status.csv.gz (FILE_FORMAT => 'csv_format');
- 变更前的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <object_size>
- 变更后的错误消息:
100082 (22000): The data length in result column $1 is not supported by this version of the client. Actual length <actual_length> exceeds supported length of 16777216.
从一个 Parquet 源查询整个大型对象¶
以下示例尝试从一个 Parquet 源查询一个大于 16 MB 的整个对象:
SELECT $1
FROM @lob_int_stage/driver_status.parquet (FILE_FORMAT => 'parquet_format');
- 变更前的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <object_size>
- 变更后的错误消息:
100082 (22000): The data length in result column $1 is not supported by this version of the client. Actual length <actual_length> exceeds supported length of 16777216.
在查询结果中包含大型对象¶
您现在可以在内存中创建大于16 MB 的对象。然而,您不能将这些对象包含在查询结果中或将它们存储在表中。当您尝试这样做时,将返回错误消息。
尝试在查询结果中包含一个大于16 MB 的对象¶
以下查询尝试连接两个大的字符串:
SELECT large_str || large_str FROM lob_strings;
- 变更前的错误消息:
100078 (22000): String '<preview_of_string>' is too long and would be truncated in 'CONCAT'
- 变更后的错误消息:
100067 (54000): The data length in result column <column_name> is not supported by this version of the client. Actual length <actual_size> exceeds supported length of 16777216.
尝试在表中存储一个大于16 MB 的对象¶
以下 CREATE TABLE AS SELECT 语句尝试连接两个大的字符串:
CREATE OR REPLACE TABLE table_varchar
AS SELECT large_str || large_str as LOB_column
FROM lob_strings;
- 变更前的错误消息:
100078 (22000): String '<preview_of_string>' is too long and would be truncated in 'CONCAT'
- 变更后的错误消息:
100067 (54000): The data length in result column <column_name> is not supported by this version of the client. Actual length <actual_size> exceeds supported length of 16777216.
使用聚合创建一个大型对象¶
当您尝试创建一个大于16 MB 的对象并返回其输出时,会返回一条错误消息。
以下示例在大型对象列的查询中使用了 ARRAY_AGG 函数:
SELECT ARRAY_AGG(status) FROM lob_object;
- 变更前的错误消息:
100082 (22000): Max LOB size (16777216) exceeded, actual size of parsed column is <actual_size>
- 变更后的错误消息:
100067 (54000): The data length in result column <column_name> is not supported by this version of the client. Actual length <actual_size> exceeds supported length of 16777216.
参考:1779