尝试获取不同值时雪花 JSON 未知关键字错误

Posted

技术标签:

【中文标题】尝试获取不同值时雪花 JSON 未知关键字错误【英文标题】:Snowflake JSON unknown keyword error when trying to get distinct values 【发布时间】:2019-11-20 04:32:35 【问题描述】:

我在 Snowflake 中有一个表,其中一个名为“值”的字段有时是纯文本有时是 JSON,该字段在 Snowflake 中存储为字符串

我创建这个视图是为了只获取 Json 格式的行

CREATE OR REPLACE VIEW tmp_events AS
    SELECT PARSE_JSON(value) as json_data,
           id
    FROM SessionEvent 
    WHERE session_event_type_id=7;

然后我将行展平以创建一个新字段

CREATE OR REPLACE VIEW tmp_events_step2 AS
     SELECT id,
            json_data:meta:selected::string AS choice
         from tmp_events ,
     LATERAL FLATTEN(input => tmp_events.json_data)
     WHERE choice IS NOT NULL

到目前为止一切正常,我可以从这两个视图中预览数据,没有错误,我得到了我期望的结果。

当我尝试从选择中获取不同的值时出现错误

 SELECT DISTINCT choice from tmp_events_step2;

解析 JSON 时出错:未知关键字“brain”,位置 6

这个名字 Brain 似乎来自我没有WHERE 语句的初始表。

如果我在没有DISTINCT 的情况下运行查询,则没有错误。

我在尝试调试时注意到的奇怪的事情:当我在 tmp_events_step2 中设置限制时,代码再次正常工作,即使我设置的限制大于表中的行数

CREATE OR REPLACE VIEW tmp_events_step2 AS
     SELECT id,
            json_data:meta:selected::string AS choice
         from tmp_events ,
     LATERAL FLATTEN(input => tmp_events.json_data)
     WHERE choice IS NOT NULL
     LIMIT 10000000;
SELECT DISTINCT choice from tmp_events_step2;

有什么收获?为什么它只适用于限制?

【问题讨论】:

【参考方案1】:

对此非常简单的答案是内置函数TRY_PARSE_JSON()

呃,不是。您似乎对查询优化器有问题,可能会执行不正确的谓词下推。防止优化器这样做的一种方法是使用安全视图选项:

CREATE SECURE VIEW tmp_events_step2 ...

并提交支持票...

【讨论】:

非常感谢!它适用于安全视图,我将向支持人员提交票证【参考方案2】:

我们在两年前报告了这个错误,他们说他们不会修复,因为在运行 WHERE 子句中的过滤器之前提升 JSON 访问,这使得强制转换有效/安全,影响性能。

create table variant_cast_bug(num number, var variant);

insert into variant_cast_bug
    select column1 as num, parse_json(column2) as var
    from values (1, '"id": 1'), 
            (1, '"id": 2'),
            (2, '"id": "text"')
            v;

select * from variant_cast_bug;
select var:id from variant_cast_bug;
select var:id from variant_cast_bug where num = 1;
select var:id::number from variant_cast_bug where num = 1; -- <- broken
select TRY_TO_NUMBER(var:id) from variant_cast_bug where num = 1; -- <- works

有时你可以嵌套select,它会起作用,然后你可以在它周围添加另一个SELECT层,做一些聚合,成本又会爆炸。

正如 Hans 提到的,仅有的两个安全解决方案是 SERCURE VIEW,但这是一场性能噩梦。 或者理解这个问题并使用TRY_TO_NUMBER或者它的朋友。

当时情况变得更糟,因为 JSON 布尔值无法传递给 TRY_TO_BOOLEAN..

有一次我们为此感到焦头烂额,是在雪花发布之后,当代码运行了一年时,开始出现此错误,因为它足够复杂,提升没有影响,然后在发布后它确实发生了。这是 Snowflake 相当敏感的地方,然后将版本回滚,我们将 TRY_TO 放在一块已经工作的 SQL 上,只是为了安全起见。

【讨论】:

损坏的代码现已修复,工作代码现已损坏。【参考方案3】:

请为此问题提交支持案例。

【讨论】:

以上是关于尝试获取不同值时雪花 JSON 未知关键字错误的主要内容,如果未能解决你的问题,请参考以下文章

在读取 JSON 时打开可选值时意外发现 nil [关闭]

volatile 关键字的两层语义

雪花 - 用“关键变化”分组

GraphicsMagick CgBI 未知关键块

尝试将 Web 表单连接到 SQL 数据库以插入值时出错

Snowflake METADATA$FILENAME 关键字在 snowsql(Unix 命令提示符)中不起作用,但在雪花 UI 中起作用