Redshift/Postgres:如何忽略生成错误的行?(json_extract_path_text中的JSON无效)

Kev*_*n S 9 postgresql amazon-redshift

我正在尝试在redshift中运行我正在选择使用的查询json_extract_path_text.不幸的是,此数据库列中的某些JSON条目无效.

会发生什么: 当查询遇到无效的JSON值时,它会因"JSON解析错误"而停止.

我想要的:忽略该列中包含无效JSON的所有行,但返回可以解析JSON的任何行.

为什么我不能让它做我想做的事情:我认为我不理解Redshift/Postgres中的错误处理.应该可以简单地跳过任何产生错误的行,但我尝试输入EXEC SQL WHENEVER SQLERROR CONTINUE(基于Postgres文档)并在"或接近SQLERROR"时出现"语法错误".

dvm*_*lls 10

创建一个python UDF:

create or replace function f_json_ok(js varchar(65535)) 
returns boolean
immutable
as $$
    if js is None: 
        return None

    import json
    try:
        json.loads(js)
        return True
    except:
        return False
$$ language plpythonu
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

select *
from schema.table
where 'DesiredValue' = 
    case 
        when f_json_ok(json_column) then json_extract_path_text(json_column, 'Key') 
        else 'nope' 
    end 
Run Code Online (Sandbox Code Playgroud)


Dav*_*ver 5

编辑:似乎Redshift 只支持 Python UDF,所以这个答案不起作用。我将把这个答案留在这里供后代使用(如果有人发现了这个没有使用 Redshift 的人)。

潜在相关:这是一个 plpgsql 函数,它将尝试解码 JSON 并在失败时返回默认值:

CREATE OR REPLACE FUNCTION safe_json(i text, fallback json) RETURNS json AS $$
BEGIN
    RETURN i::json;
EXCEPTION
    WHEN others THEN
        RETURN fallback;
END;
$$ LANGUAGE plpgsql IMMUTABLE RETURNS NULL ON NULL INPUT;
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

SELECT
    …
FROM (
    SELECT safe_json(my_text, '{"error": "invalid JSON"}'::json) AS my_json
    FROM my_table
) as x
Run Code Online (Sandbox Code Playgroud)

保证您始终拥有有效的 JSON

  • 这显然在 redshift 中不起作用,因为“[0A000] 错误:语言 plpgsql 不支持创建函数。” (2认同)

har*_*mic 2

我假设 JSON 数据实际上存储在 TEXT 列而不是 JSON 列中(否则您一开始就无法在其中存储非 JSON)。

如果数据存在某种模式,允许您创建一个正则表达式来检测有效行或无效行,那么您可以使用 CASE 语句。例如:

SELECT CASE
    WHEN mycol !~ 'not_json' THEN json_extract_path_text(mycol, ....)
    ELSE NULL
END AS mystuff
...
Run Code Online (Sandbox Code Playgroud)

将 not_json 替换为检测非 JSON 格式值的正则表达式。

这可能实用也可能不实用,具体取决于数据的格式。

根据这个问题的答案,显然可以使用一些正则表达式实现来完全验证任意 JSON 数据,但可惜不是 postgresql 使用的那个。