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 正是您想要的。但是这种形式对于数据处理来说并不是特别好。如果需要,您可能希望使用一些文本处理脚本来处理数据。