STRIP_OUTER_ARRAY 支持什么 JSON 格式?
What JSON format does STRIP_OUTER_ARRAY support?
我有一个由包含多个记录的单个数组组成的文件。
{
"Client": [
{
"ClientNo": 1,
"ClientName": "Alpha",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "12345"
},
{
"BusinessNo": 2,
"IndustryCode": "23456"
}
]
},
{
"ClientNo": 2,
"ClientName": "Bravo",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "34567"
},
{
"BusinessNo": 2,
"IndustryCode": "45678"
}
]
}
]
}
我用下面的代码加载它:
create or replace stage stage.test
url='azure://xxx/xxx'
credentials=(azure_sas_token='xxx');
create table if not exists stage.client (json_data variant not null);
copy into stage.client_test
from @stage.test/client_test.json
file_format = (type = 'JSON' strip_outer_array = true);
Snowflake 将整个文件导入为一行。
我希望 COPY INTO 命令删除外部数组结构并将记录加载到单独的 table 行中。
当我加载较大的文件时,我达到了变体的大小限制并收到错误 Error parsing JSON: document is too large, max size 16777216 bytes
。
建议 #1:
您的 JSON 的问题在于它没有外部数组。它有一个包含 属性 和内部数组的单个外部对象。
如果你能修复 JSON,那将是最好的解决方案,然后 STRIP_OUTER_ARRAY 就会如你所愿。
您也可以在阅读以下行后尝试重组 JSON(丑陋的业务):
CREATE OR REPLACE TABLE X (CLIENT VARCHAR);
COPY INTO X FROM (SELECT CLIENT FROM @My_Stage/Client.json);
用户对建议 #1 的响应:
谢谢。所以据我所知,COPY with STRIP_OUTER_ARRAY
可以处理以方括号开头和结尾的文件,并像它们不存在一样解析文件。
真正的文件没有换行符,所以我无法逐行读取文件。我看看源系统能不能改导出。
建议 #2:
此外,如果您想查看 JSON 解析器的功能,您可以使用此代码进行试验,我已经使用类似代码在复制命令上解析了 JSON。在小型项目中处理 JSON 数据可以帮助您调整复制命令以使其按预期工作。
CREATE OR REPLACE TABLE SAMPLE_JSON
(ID INTEGER,
DATA VARIANT
);
INSERT INTO SAMPLE_JSON(ID,DATA)
SELECT
1,parse_json('{
"Client": [
{
"ClientNo": 1,
"ClientName": "Alpha",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "12345"
},
{
"BusinessNo": 2,
"IndustryCode": "23456"
}
]
},
{
"ClientNo": 2,
"ClientName": "Bravo",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "34567"
},
{
"BusinessNo": 2,
"IndustryCode": "45678"
}
]
}
]
}');
SELECT
C.value:ClientNo AS ClientNo
,C.value:ClientName::STRING AS ClientName
,ClientBusiness.value:BusinessNo::Integer AS BusinessNo
,ClientBusiness.value:IndustryCode::Integer AS IndustryCode
from SAMPLE_JSON f
,table(flatten( f.DATA,'Client' )) C
,table(flatten(c.value:ClientBusiness,'')) ClientBusiness;
用户对建议 #2 的响应:
感谢您提供 parse_json 示例!
问题是,真实的文件有时有 500 MB,所以 parse_json 函数会卡住。
建议 #2 的跟进:
JSON需要NDJSONhttp://ndjson.org/格式。否则 JSON 将无法解析,因为可能存在大文件。
希望以上内容能帮助其他运行解决类似问题!
如果您可以将文件导入到 Snowflake 中,导入到一行中,那么您可以在 Clients 字段上使用 LATERAL FLATTEN 为数组中的每个元素生成一行。
这是一篇关于 LATERAL 和 FLATTEN 的博客 post(或者您可以在雪花文档中查找它们):
https://support.snowflake.net/s/article/How-To-Lateral-Join-Tutorial
如果文件的格式如指定的那样是具有单个 属性 的单个对象,其中包含一个包含 500 MB 元素的数组,那么导入它也许仍然有效——如果行得通,那么 LATERAL FLATTEN 正是您想要的。但是这种形式对于数据处理来说并不是特别好。如果需要,您可能希望使用一些文本处理脚本来处理数据。
我有一个由包含多个记录的单个数组组成的文件。
{
"Client": [
{
"ClientNo": 1,
"ClientName": "Alpha",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "12345"
},
{
"BusinessNo": 2,
"IndustryCode": "23456"
}
]
},
{
"ClientNo": 2,
"ClientName": "Bravo",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "34567"
},
{
"BusinessNo": 2,
"IndustryCode": "45678"
}
]
}
]
}
我用下面的代码加载它:
create or replace stage stage.test
url='azure://xxx/xxx'
credentials=(azure_sas_token='xxx');
create table if not exists stage.client (json_data variant not null);
copy into stage.client_test
from @stage.test/client_test.json
file_format = (type = 'JSON' strip_outer_array = true);
Snowflake 将整个文件导入为一行。
我希望 COPY INTO 命令删除外部数组结构并将记录加载到单独的 table 行中。
当我加载较大的文件时,我达到了变体的大小限制并收到错误 Error parsing JSON: document is too large, max size 16777216 bytes
。
建议 #1:
您的 JSON 的问题在于它没有外部数组。它有一个包含 属性 和内部数组的单个外部对象。
如果你能修复 JSON,那将是最好的解决方案,然后 STRIP_OUTER_ARRAY 就会如你所愿。
您也可以在阅读以下行后尝试重组 JSON(丑陋的业务):
CREATE OR REPLACE TABLE X (CLIENT VARCHAR);
COPY INTO X FROM (SELECT CLIENT FROM @My_Stage/Client.json);
用户对建议 #1 的响应:
谢谢。所以据我所知,COPY with STRIP_OUTER_ARRAY
可以处理以方括号开头和结尾的文件,并像它们不存在一样解析文件。
真正的文件没有换行符,所以我无法逐行读取文件。我看看源系统能不能改导出。
建议 #2:
此外,如果您想查看 JSON 解析器的功能,您可以使用此代码进行试验,我已经使用类似代码在复制命令上解析了 JSON。在小型项目中处理 JSON 数据可以帮助您调整复制命令以使其按预期工作。
CREATE OR REPLACE TABLE SAMPLE_JSON
(ID INTEGER,
DATA VARIANT
);
INSERT INTO SAMPLE_JSON(ID,DATA)
SELECT
1,parse_json('{
"Client": [
{
"ClientNo": 1,
"ClientName": "Alpha",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "12345"
},
{
"BusinessNo": 2,
"IndustryCode": "23456"
}
]
},
{
"ClientNo": 2,
"ClientName": "Bravo",
"ClientBusiness": [
{
"BusinessNo": 1,
"IndustryCode": "34567"
},
{
"BusinessNo": 2,
"IndustryCode": "45678"
}
]
}
]
}');
SELECT
C.value:ClientNo AS ClientNo
,C.value:ClientName::STRING AS ClientName
,ClientBusiness.value:BusinessNo::Integer AS BusinessNo
,ClientBusiness.value:IndustryCode::Integer AS IndustryCode
from SAMPLE_JSON f
,table(flatten( f.DATA,'Client' )) C
,table(flatten(c.value:ClientBusiness,'')) ClientBusiness;
用户对建议 #2 的响应:
感谢您提供 parse_json 示例!
问题是,真实的文件有时有 500 MB,所以 parse_json 函数会卡住。
建议 #2 的跟进:
JSON需要NDJSONhttp://ndjson.org/格式。否则 JSON 将无法解析,因为可能存在大文件。
希望以上内容能帮助其他运行解决类似问题!
如果您可以将文件导入到 Snowflake 中,导入到一行中,那么您可以在 Clients 字段上使用 LATERAL FLATTEN 为数组中的每个元素生成一行。
这是一篇关于 LATERAL 和 FLATTEN 的博客 post(或者您可以在雪花文档中查找它们): https://support.snowflake.net/s/article/How-To-Lateral-Join-Tutorial
如果文件的格式如指定的那样是具有单个 属性 的单个对象,其中包含一个包含 500 MB 元素的数组,那么导入它也许仍然有效——如果行得通,那么 LATERAL FLATTEN 正是您想要的。但是这种形式对于数据处理来说并不是特别好。如果需要,您可能希望使用一些文本处理脚本来处理数据。