如何在 H2 中将 JSON 字符串值转换为 VARCHAR 值(不包括引号)?

问题描述 投票:0回答:1

我有一个 H2 数据库(版本 2.2.220),数据位于

JSON
列中;我需要通过 SQL 脚本迁移列,以便数据处于传统的关系数据库结构中。主要的障碍是在提取 JSONValue 字符串值(用 JSON 格式的双引号括起来)时,我正在努力将其转换为不包含周围双引号的
VARCHAR
值。

我希望下面的 SQL 语句能够以最基本的方式说明这个问题:

  1. create table my_table (
        id        int generated by default as identity,
        my_json   JSON null default null,
    );
    
    insert into my_table (my_json) values (JSON '"abcdef"');
    
    字符串常量内的双引号是必需的,否则它不会被识别为有效的 JSON。
  2. 第一个查询(简单):
    select my_json from my_table;
    
    这将返回
    "abcdef"
    ,字符串中包含引号。不过,我希望返回原始字符串值
    abcdef
    ,而不带周围的引号。
  3. 第二个查询(类型转换):
    select CAST(my_json as VARCHAR(255)) from my_table;
    
    这仍然返回
    "abcdef"
    ,字符串中包含引号。
  4. 第 3 查询(“暴力”修剪):
    select BTRIM(my_json, '"') from my_table;
    
    这达到了预期的结果
    abcdef
    ,但是有问题。导致错误的一种方式是字符串值应故意在开头和/或结尾处包含双引号,例如
    xyz"
    (
    JSON '"xyz\""'
    ) - 这将被修剪以返回
    xyz\

我想知道是否有一种“推荐”/更干净的方法来进行这种转换,并且不易出现错误。

相关/有趣

sql json h2
1个回答
0
投票

恐怕在 H2 数据库中实现此目的最安全的方法是使用用户定义函数(UDF)。不幸的是,没有直接的方法可以使用 H2 的内置函数删除这些引号,因为 H2 数据库不允许直接查询单个 JSON 值。 H2 将 JSON 数据存储为纯字符串。因此,当您将

"abcdef"
保存到表中时(无论您使用
JSON '"abcdef"'
还是
'abcdef'::JSON
),查询
select my_json from my_table;
始终返回整个 JSON 对象(即
"abcdef"
),而不仅仅是值 (
) abcdef
),就像您查询 JSON 对象(例如
select JSON '{"foo":"bar"}';
)一样,没有本地方法可以从
bar
字段中提取
foo
值。

因此,如果您需要单独的值,我建议创建这样的 UDF:

DROP ALIAS IF EXISTS STRIP_JSON_QUOTES;

CREATE ALIAS STRIP_JSON_QUOTES AS $$
String strip_json_quotes(String jsonString) {
    if (jsonString != null && !jsonString.isEmpty()) {
        if (jsonString.startsWith("\"") && jsonString.endsWith("\"") && jsonString.length() > 1) {
            return jsonString.substring(1, jsonString.length() - 1);
        }
    }
    return jsonString;
}
$$;

然后你可以这样称呼它:

select strip_json_quotes(my_json) from my_table;

我不建议使用

BTRIM
因为它会删除所有前导和尾随字符,而不仅仅是最外面的字符。例如,在极少数情况下,您想要存储带引号的值,BTRIM 会删除太多内容:

sql> select BTRIM('"abcdef"'::JSON, '"') as trimmed_json_value;
TRIMMED_JSON_VALUE
\"abcdef\
(1 row, 29 ms)
© www.soinside.com 2019 - 2024. All rights reserved.