SQL 数据类型:最大长度、输出和错误消息的变更(待定)

注意

此行为变更包含在 2024_08 捆绑包中。

有关捆绑包的当前状态,请参阅 捆绑包历史记录

随着此行为变更,编译后的 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 valuecannot 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
  $$;
Copy

GET_DDL

调用 GET_DDL 函数所返回的元数据会发生如下更改:

SELECT GET_DDL('function', 'udf_varchar(VARCHAR)');
Copy
变更前的元数据:
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);
Copy
变更前的元数据:
+-----------+-------------------+
| 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"
}
Copy
变更后的元数据:
{
  "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"
}
Copy

返回具有列表达式的表的元数据

对于在列表达式中使用 VARCHAR 或 BINARY 的新表,与这些列相关的 DDL 语句的元数据变更会影响调用 GET_DDL 函数时返回的输出。

以下示例创建一个具有列表达式的表。

CREATE OR REPLACE TABLE table_with_default(x INT, v TEXT DEFAULT x::VARCHAR);
Copy

调用 GET_DDL 函数所返回的元数据会发生如下更改:

SELECT GET_DDL('table', 'table_with_default');
Copy
变更前的元数据:
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);
Copy

调用 GET_DDL 函数所返回的元数据会发生如下更改:

SELECT GET_DDL('table', 'ext_table');
Copy
变更前的元数据:
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));
Copy
变更前的元数据:
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;
Copy
变更前的元数据:
{
  "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');
Copy
变更前的错误消息:
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');
Copy
变更前的错误消息:
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'));
Copy
变更前的错误消息:
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'));
Copy
变更前的错误消息:
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'));
Copy
变更前的错误消息:
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);
Copy
变更前的错误消息:
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);
Copy
变更前的错误消息:
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');
Copy
变更前的错误消息:
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');
Copy
变更前的错误消息:
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');
Copy
变更前的错误消息:
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');
Copy
变更前的错误消息:
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;
Copy
变更前的错误消息:
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;
Copy
变更前的错误消息:
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;
Copy
变更前的错误消息:
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

语言: 中文