SQLite数据库中JSON 函数和运算符(二十七)

返回:SQLite—系列文章目录   

上一篇:维护SQLite的私有分支(二十六)

下一篇:SQLite—系列文章目录   

​1. 概述

默认情况下,SQLite 支持 29 个函数和 2 个运算符 处理 JSON 值。还有两个表值函数可用于分解 JSON 字符串。

有 25 个标量函数和运算符:

  1. json(json)
  2. jsonb(json)
  3. json_array(value1,value2,...)
  4. jsonb_array(value1,value2,...)
  5. json_array_length(json)
    json_array_length(json,path)
  6. json_error_position(json)
  7. json_extract(json,path,...)
  8. jsonb_extract(json,path,...)
  9. json -> path
  10. json ->> path
  11. json_insert(json,path,value,...)
  12. jsonb_insert(json,path,value,...)
  13. json_object(label1,value1,...)
  14. jsonb_object(label1,value1,...)
  15. json_patch(json1,json2)
  16. jsonb_patch(json1,json2)
  17. json_remove(json,path,...)
  18. jsonb_remove(json,path,...)
  19. json_replace(json,path,value,...)
  20. jsonb_replace(json,path,value,...)
  21. json_set(json,path,value,...)
  22. jsonb_set(json,path,value,...)
  23. json_type(json)
    json_type(json,path)
  24. json_valid(json)
    json_valid(json,flags)
  25. json_quote(value)

有四个聚合 SQL 函数:

  1. json_group_array(value)
  2. jsonb_group_array(value)
  3. json_group_object(label,value)
  4. jsonb_group_object(name,value)

这两个表值函数是:

  1. json_each(json)
    json_each(json,path)
  2. json_tree(json)
    json_tree(json,path)

2. 在 JSON 支持下编译

默认情况下,JSON 函数和运算符内置于 SQLite 中, 自 SQLite 版本 3.38.0 (2022-02-22) 起。可以省略它们 通过添加 -DSQLITE_OMIT_JSON 编译时选项。之前 版本 3.38.0,JSON 函数是一个扩展,只会 如果 -DSQLITE_ENABLE_JSON1 编译时选项包含在构建中 被包括在内。换句话说,JSON 函数从 选择加入 SQLite 版本 3.37.2 及更早版本以选择退出 SQLite 版本 3.38.0 及更高版本。

3. 接口概述

SQLite将JSON存储为普通文本。 向后兼容性约束意味着 SQLite 只能 存储 NULL、整数、浮点数、文本、 和 BLOB。无法添加新的“JSON”类型。

3.1. JSON参数

对于接受 JSON 作为其第一个参数的函数,该参数 可以是 JSON 对象、数组、数字、字符串或 null。SQLite 数值 values 和 NULL 值分别解释为 JSON 编号和 null。 SQLite 文本值可以理解为 JSON 对象、数组或字符串。 如果 SQLite 文本值不是格式正确的 JSON 对象、数组或 字符串被传递到 JSON 函数中,该函数通常会抛出 一个错误。(此规则的例外情况是 json_valid()、json_quote() 和 json_error_position()。

这些例程了解所有 rfc-8259 JSON 语法以及 JSON5 扩展。JSON 文本 这些例程生成的例程始终严格符合规范的 JSON 定义,并且不包含任何 JSON5 或其他扩展名。添加了读取和理解 JSON5 的功能 版本 3.42.0 (2023-05-16). 以前版本的 SQLite 只能读取规范的 JSON。

3.2. JSONB的

从版本 3.45.0 (2024-01-15) 开始,SQLite 允许其 要存储在磁盘上的 JSON 的内部“解析树”表示, 作为 BLOB,采用我们称之为“JSONB”的格式。通过存储 SQLite 的内部 JSON的二进制表示直接在数据库、应用程序中 可以绕过解析和渲染 JSON 的开销,读取和 更新 JSON 值。内部 JSONB 格式也略有使用 更少的磁盘空间,然后文本 JSON。

任何接受文本 JSON 作为输入的 SQL 函数参数也将 接受 JSONB 格式的 BLOB。该函数将操作 在任何一种情况下都是一样的,除了它在以下情况下会运行得更快 输入是 JSONB,因为它不需要运行 JSON 解析器。

大多数返回 JSON 文本的 SQL 函数都有相应的函数 返回等效的 JSONB。返回 JSON 的函数 在文本格式中,以“json_”开头,其功能是 返回以“jsonb_”开头的二进制 JSONB 格式。

3.2.1. JSONB格式

JSONB 是 SQLite 和 仅供 SQLite 内部使用。应用 不应在 SQLite 之外使用 JSONB,也不应尝试对 JSONB 格式。

“JSONB”名称的灵感来自 PostgreSQL,但 SQLite 的 JSONB 的磁盘格式与 PostgreSQL 的磁盘格式不同。 这两种格式具有相同的名称,但不兼容二进制文件。 PostgreSQL JSONB 格式声称提供 O(1) 查找对象和数组中的元素。SQLite 的 JSONB 格式没有 这种说法。SQLite 的 JSONB 具有 O(N) 时间复杂度 SQLite中的大多数操作,就像文本JSON一样。JSONB的优势 SQLite 是它比文本 JSON 更小、更快——可能有几个 快几倍。有空间 磁盘上的JSONB格式,以添加增强功能,并且SQLite的未来版本可能会 include 选项来提供 JSONB 中元素的 O(1) 查找,但没有这样的选项 该功能目前可用。

3.2.2. 处理畸形的 JSONB

SQLite 生成的 JSONB 将始终格式正确。如果你 遵循推荐的做法,并 将 JSONB 视为不透明的 BLOB,那么您就不会有任何问题。但 JSONB 只是一个 BLOB,所以一个淘气的程序员可以设计 BLOB 与 JSONB 类似,但在技术上格式不正确。什么时候 格式错误的 JSONB 被馈送到 JSON 函数中,以下任一 可能发生:

  • SQL 语句可能会中止,并显示“格式错误的 JSON”错误。

  • 如果 JSONB blob 不会影响答案。

  • 可能会返回一个愚蠢或荒谬的答案。

SQLite 处理无效 JSONB 的方式可能会改变 从一个版本的SQLite到下一个版本。系统遵循 垃圾输入/垃圾输出规则:如果馈送 JSON 函数无效 JSONB,你得到一个无效的答案。如果您对 我们的 JSONB 的有效性,请使用 json_valid() 函数进行验证。

我们做出以下承诺: 格式错误的 JSONB 永远不会引起内存 错误或可能导致漏洞的类似问题。 无效的 JSONB 可能会导致疯狂的答案, 或者,它可能会导致查询中止,但不会导致崩溃。

3.3. PATH参数

对于接受 PATH 参数的函数,该 PATH 必须格式正确或 否则,该函数将抛出错误。 格式正确的 PATH 是以 1 开头的文本值 “$”字符后跟零个或多个实例 的“。objectlabel“或”[arrayindex]“。

数组索引通常是一个非负整数 N。在 在这种情况下,选择的数组元素是第 N 个元素 数组,从左边的零开始。 数组索引也可以采用“#-N”的形式 在这种情况下,选择的元素是 右。数组的最后一个元素是“#-1”。念 “#”字符作为“数组中的元素数”。然后 表达式“#-1”的计算结果为对应于 数组中的最后一个条目。它有时对数组很有用 index 仅为 # 字符,例如在追加 现有 JSON 数组的值:

  • json_set('[0,1,2]','$[#]','new') → '[0,1,2,"new"]'

3.4. VALUE 参数

对于接受“”参数的函数(也称为 “value1” 和 “value2”), 这些论点通常被理解 成为带引号并成为 JSON 字符串值的文本字符串 在结果中。即使输入字符串如下所示 格式良好的 JSON,它们仍然被解释为 结果。

但是,如果一个值参数直接来自另一个参数的结果 JSON 函数或来自 -> 运算符(但不是 ->> 运算符), 则参数被理解为实际的 JSON 和 插入完整的 JSON,而不是带引号的字符串。

例如,在下面对 json_object() 的调用中,value 参数看起来像一个格式正确的 JSON 数组。但是,因为它只是 普通的 SQL 文本,它被解释为文字字符串并添加到 结果为带引号的字符串:

  • json_object('ex','[52,3.14159]') → '{"ex":"[52,3.14159]"}'
  • json_object('ex',('[52,3.14159]'->>'$')) → '{"ex":"[52,3.14159]"}'

但是,如果外部 json_object() 调用中的 value 参数是 另一个 JSON 函数(如 json() 或 json_array())的结果,则 该值被理解为实际的 JSON,并按如下方式插入:

  • json_object('ex',json('[52,3.14159]')) → '{"ex":[52,3.14159]}'
  • json_object('ex',json_array(52,3.14159)) → '{"ex":[52,3.14159]}'
  • json_object('ex','[52,3.14159]'->'$') → '{"ex":[52,3.14159]}'

需要明确的是:“json”参数总是被解释为 JSON 无论该参数的值来自何处。但 “value”参数仅在以下情况下被解释为 JSON: 直接来自另一个 JSON 函数或 -> 运算符。

在解释为 JSON 字符串的 JSON 值参数中,Unicode 转义 序列不被视为等同于字符或转义 由表示的 Unicode 码位表示的控制字符。 此类转义序列未进行翻译或特殊处理;他们 被 SQLite 的 JSON 函数视为纯文本。

3.5. 兼容性

此 JSON 库的当前实现使用递归下降 解析 器。为了避免使用过多的堆栈空间,任何具有 超过 1000 级的嵌套被认为是无效的。嵌套限制 RFC-8259 第 9 节允许 JSON 的兼容实现进行深度。

3.6. JSON5扩展

从版本 3.42.0 (2023-05-16) 开始,这些例程将 读取和解释包含 JSON5 扩展的输入 JSON 文本。但是,生成的 JSON 文本 通过这些例程将始终严格符合 JSON 的规范定义。

以下是 JSON5 扩展的概要(改编自 JSON5 规范):

  • 对象键可以是不带引号的标识符。
  • 对象可以有一个尾部逗号。
  • 数组可以有一个尾随逗号。
  • 字符串可以单引号。
  • 字符串可以通过转义换行符来跨越多行。
  • 字符串可能包含新的字符转义。
  • 数字可以是十六进制的。
  • 数字可以有前导或尾随小数点。
  • 数字可以是“Infinity”、“-Infinity”和“NaN”。
  • 数字可以以明确的加号开头。
  • 允许使用单行 (//...) 和多行 (/*...*/) 注释。
  • 允许使用其他空格字符。

要将字符串 X 从 JSON5 转换为规范 JSON,请调用 “json(X)”。“json()”函数的输出将是规范的 JSON,而不考虑输入中存在的任何 JSON5 扩展。 为了向后兼容,没有 json_valid(X) 函数 “flags”争论仍在继续 为非规范 JSON 的输入报告 false,即使 输入是函数能够理解的 JSON5。确定 无论输入字符串是否有效 JSON5,都包含 0x02 位 在“flags”参数中json_valid:“json_valid(X,2)”。

这些例程可以理解 JSON5 的所有内容,以及更多内容。 SQLite 通过以下两种方式扩展 JSON5 语法:

  1. 严格的 JSON5 要求 不带引号的对象键必须是 ECMAScript 5.1 IdentifierNames。但很大 需要 Unicode 表和大量代码来确定是否或 not a key 是 ECMAScript 5.1 IdentifierName。出于这个原因, SQLite 允许对象键包含任何 unicode 字符 大于 U+007f,不是空格字符。这放松 “标识符”的定义大大简化了实现,并允许 JSON 解析器更小,运行更快。

  2. JSON5 允许将浮点无穷大表示为 “无穷大”、“-无穷大”或“+无穷大” 正是在这种情况下 - 首字母“I”是大写的,所有其他 字符为小写。SQLite还允许缩写“Inf” 用于代替“Infinity”,它允许两个关键字 以大小写字母的任意组合出现。 同样地 JSON5 允许“NaN”表示非数字。SQLite扩展了这一点,也允许 “QNaN”和“SNaN”大写和小写字母的任意组合。 请注意,SQLite 将 NaN、QNaN 和 SNaN 解释为一种替代方案 “null”的拼写。 添加此扩展是因为(我们被告知)存在很多 包含这些非标准表示的 JSON 在野外 对于无穷大和非数字。

3.7. 性能注意事项

大多数 JSON 函数使用 JSONB 进行内部处理。因此,如果 输入是文本,他们首先必须将输入文本翻译成 JSONB。 如果输入已经是 JSONB 格式,则不需要翻译, 可以跳过该步骤,并且性能更快。

出于这个原因, 当一个 JSON 函数的参数由另一个 JSON 函数提供时 JSON函数,通常使用“jsonb_”更有效率 用作参数的函数的变体。

  • ... json_insert(A,'$.b',json(C)) ...   ← 效率较低。
  • ... json_insert(A,'$.b',jsonb(C)) ...   ←效率更高。

聚合 JSON SQL 函数是此规则的例外。那些 所有函数都使用文本而不是 JSONB 进行处理。所以对于 聚合JSON SQL函数,对参数更有效率 使用“json_”功能而不是“jsonb_”提供 功能。

  • ... json_group_array(json(A))) ...   ←效率更高。
  • ... json_group_array(jsonb(A))) ...   ←效率较低。

3.8. JSON BLOB 输入错误

如果 JSON 输入是不是 JSONB 的 BLOB,并且看起来像 text JSON 转换为文本时,则将其接受为文本 JSON。 这实际上是原始实现中长期存在的错误 SQLite开发人员不知道。文件指出 JSON 函数的 BLOB 输入应引发错误。但是在 实际实施,只要输入将被接受 因为 BLOB 内容是文本编码中的有效 JSON 字符串 数据库。

当 JSON 例程 在 3.45.0 版本 (2024-01-15) 中重新实现。 这导致了依赖旧应用程序的损坏 行为。(为了捍卫这些应用程序:他们经常被引诱进入 通过 readfile() SQL 函数将 BLOB 用作 JSON 在 CLI 中可用。Readfile() 用于从磁盘文件中读取 JSON, 但 readfile() 返回一个 BLOB。这对他们有用,所以为什么不直接 做吗?

为了向后兼容, 将 BLOB 解释为文本 JSON 的(以前不正确的)遗留行为 如果没有其他解释有效 特此记录在案,并在 版本 3.45.1 (2024-01-30) 和所有后续版本。

4. 功能细节

以下各节提供了有关操作的更多详细信息 各种 JSON 函数和运算符:

4.1. json()函数

json(X) 函数验证其参数 X 是否有效 JSON 字符串或 JSONB blob,并返回该 JSON 字符串的缩小版本 删除了所有不必要的空格。如果 X 不是格式良好的 JSON 字符串或 JSONB blob,则此例程会引发错误。

如果输入是 JSON5 文本,则将其转换为规范文本 RFC-8259 文本之前返回。

如果参数 X 到 json(X) 包含重复的 JSON 对象 标签,则未定义重复项是否是 保存。当前实现保留重复项。 但是,未来的增强功能 对于此例程,可以选择静默删除重复项。

例:

  • json(' { "this" : "is", "a": [ "test" ] } ') → '{"this":"is","a":["test"]}'

4.2. jsonb()函数

jsonb(X) 函数返回二进制 JSONB 表示形式 作为参数 X 提供的 JSON。如果 X 是 没有有效 JSON 语法的 TEXT。

如果 X 是 BLOB 并且显示为 JSONB, 那么这个例程只返回一个 X 的副本。 但是,仅检查 JSONB 输入的最外层元素。 JSONB 的深层结构未经过验证。

4.3. json_array() 函数

json_array() SQL 函数接受零个或多个参数,并且 返回由这些参数组成的格式正确的 JSON 数组。 如果 json_array() 的任何参数是 BLOB,则会引发错误。

SQL 类型为 TEXT 的参数通常转换为带引号的参数 JSON 字符串。但是,如果参数是另一个 json1 的输出 函数,则将其存储为 JSON。这允许调用 json_array() 和 json_object() 要嵌套。json() 函数还可以 用于强制将字符串识别为 JSON。

例子:

  • json_array(1,2,'3',4) → '[1,2,"3",4]'
  • json_array('[1,2]') → '["[1,2]"]'
  • json_array(json_array(1,2)) → '[[1,2]]'
  • json_array(1,null,'3','[4,5]','{"six":7.7}') → '[1,null,"3","[4,5]","{\"six\":7.7}"]'
  • json_array(1,null,'3',json('[4,5]'),json('{"six":7.7}')) → '[1,null,"3",[4,5],{"six":7.7}]'

4.4. jsonb_array()函数

jsonb_array()SQL 函数的工作方式与 json_array() 函数类似,只是它返回 SQLite的私有JSONB格式,而不是标准格式 RFC 8259 文本格式。

4.5. json_array_length()函数

json_array_length(X) 函数返回元素数 在 JSON 数组 X 中,如果 X 是某种 JSON 值,则为 0 其他 比数组。json_array_length(X,P) 将数组定位在路径 P 处 在 X 中并返回该数组的长度,如果路径 P 定位,则返回 0 X 中不是 JSON 数组的元素,如果路径 P 不是 NULL 找到 X 的任何元素。如果任一 X 不是,则会引发错误 格式正确的 JSON,或者如果 P 不是格式正确的路径。

例子:

  • json_array_length('[1,2,3,4]') → 4
  • json_array_length('[1,2,3,4]', '$') → 4
  • json_array_length('[1,2,3,4]', '$[2]') → 0
  • json_array_length('{"one":[1,2,3]}') → 0
  • json_array_length('{"one":[1,2,3]}', '$.one') → 3
  • json_array_length('{"one":[1,2,3]}', '$.two') → NULL

4.6. json_error_position()函数

json_error_positionf如果输入 X 为 格式正确的 JSON 或 JSON5 字符串。如果输入 X 包含一个或多个 语法错误,则此函数返回 第一个语法错误。最左边的字符是位置 1。

如果输入 X 是 BLOB,则如果 X 是 格式正确的 JSONB blob。如果返回值为正,则 表示 BLOB 中从 1 开始的近似位置 首次检测到错误。

添加了 json_error_position()函数 SQLite 版本 3.42.0 (2023-05-16).

4.7. json_extract()函数

json_extract(X,P1,P2,...) 提取并返回一个或多个 值从 X 处格式良好的 JSON。如果只提供了单个路径 P1,则 对于 JSON null、INTEGER 或 REAL,结果的 SQL 数据类型为 NULL 对于 JSON 数值,对于 JSON false 值,INTEGER 零, 一个 INTEGER 一个表示 JSON true 值,一个 JSON 字符串值,以及 JSON 对象和数组值的文本表示形式。 如果有多个路径参数(P1、P2 等),那么这个 例程返回 SQLite 文本,该文本是一个格式良好的 JSON 数组,保存 各种值。

例子:

  • json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$') → '{"a":2,"c":[4,5,{"f":7}]}'
  • json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c') → '[4,5,{"f":7}]'
  • json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]') → '{"f":7}'
  • json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f') → 7
  • json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a') → '[[4,5],2]'
  • json_extract('{"a":2,"c":[4,5],"f":7}','$.c[#-1]') → 5
  • json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x') → NULL
  • json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a') → '[null,2]'
  • json_extract('{"a":"xyz"}', '$.a') → 'xyz'
  • json_extract('{"a":null}', '$.a') → NULL

json_extract()函数之间存在微妙的不兼容性 在 SQLite 和 MySQL 中的 json_extract()函数。MySQL版本 of json_extract()始终返回 JSON。SQLite 版本 json_extract() 仅在存在两个或多个 PATH 参数时返回 JSON (因为结果是一个 JSON 数组)或者如果单个 PATH 参数 引用数组或对象。在SQLite中,如果json_extract()只有 单个 PATH 参数,并且该 PATH 引用 JSON null 或字符串 或数值,则 json_extract()返回相应的 SQL NULL、TEXT、INTEGER 或 REAL 值。

MySQL json_extract()和 SQLite json_extract()之间的区别 只有在访问 JSON 中的单个值时才真正脱颖而出 是字符串或 NULL。下表演示了差异:

操作SQLite 结果MySQL 结果
json_extract('{“a”:null,“b”:“xyz”}','$.a')“空”
json_extract('{“a”:null,“b”:“xyz”}','$.b')“xyz”'“xyz”'

4.8. jsonb_extract()函数

jsonb_extract()函数的工作方式与 json_extract() 函数相同, 除非 json_extract() 通常会返回文本 JSON 数组对象,此例程返回 JSONB 格式。对于文本、数字、null 或 返回布尔 JSON 元素,此例程的工作方式完全相同 如 json_extract()。

4.9. -> 和 ->> 运算符

从 SQLite 版本 3.38.0 (2022-02-22) 开始,-> 和 ->> 运算符可用于提取 JSON 的子组件。 -> 和 ->> 的 SQLite 实现力求 与 MySQL 和 PostgreSQL 兼容。 -> 和 ->> 运算符采用 JSON 字符串或 JSONB blob 作为其左操作数和 PATH 表达式或对象字段 label 或 array index 作为其右操作数。-> 运算符 返回所选子组件的文本 JSON 表示形式,或者 如果该子组件不存在,则为 NULL。->> 运算符返回 一个 SQL TEXT、INTEGER、REAL 或 NULL 值,表示所选 子组件,如果子组件不存在,则为 NULL。

-> 和 ->> 运算符都选择相同的子组件 JSON在他们左边。区别在于 -> 总是返回一个 该子组件和 ->> 运算符的 JSON 表示形式始终如此 返回该子组件的 SQL 表示形式。因此,这些运算符 与双参数 json_extract() 函数调用略有不同。 使用两个参数调用 json_extract() 将返回 JSON 表示形式 当且仅当子组件是 JSON 数组或 对象,如果 subcomponent 是 JSON 空值、字符串值或数值。

当 -> 运算符返回 JSON 时,它始终返回 该 JSON 的 RFC 8565 文本表示形式,而不是 JSONB。使用 jsonb_extract() 函数,如果您需要 JSONB 格式。

-> 和 ->> 运算符的右操作数可以 是格式正确的 JSON 路径表达式。这是MySQL使用的形式。 为了与 PostgreSQL 兼容, -> 和 ->> 运算符也接受文本对象标签或 整数数组索引作为其右手操作数。 如果正确的操作数是文本 标签 X,则将其解释为 JSON 路径 '$。X'.如果正确的 operand 是一个整数值 N,则将其解释为 JSON 路径“$[N]”。

例子:

  • '{"a":2,"c":[4,5,{"f":7}]}' -> '$' → '{"a":2,"c":[4,5,{"f":7}]}'
  • '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c' → '[4,5,{"f":7}]'
  • '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' → '[4,5,{"f":7}]'
  • '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c[2]' → '{"f":7}'
  • '{"a":2,"c":[4,5,{"f":7}]}' -> '$.c[2].f' → '7'
  • '{"a":2,"c":[4,5,{"f":7}]}' ->> '$.c[2].f' → 7
  • '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2 ->> 'f' → 7
  • '{"a":2,"c":[4,5],"f":7}' -> '$.c[#-1]' → '5'
  • '{"a":2,"c":[4,5,{"f":7}]}' -> '$.x' → NULL
  • '[11,22,33,44]' -> 3 → '44'
  • '[11,22,33,44]' ->> 3 → 44
  • '{"a":"xyz"}' -> '$.a' → '"xyz"'
  • '{"a":"xyz"}' ->> '$.a' → 'xyz'
  • '{"a":null}' -> '$.a' → 'null'
  • '{"a":null}' ->> '$.a' → NULL

4.10. json_insert()、json_replace 和 json_set()函数

json_insert()、json_replace 和 json_set()函数都采用 单个 JSON 值作为其第一个参数,后跟零或更多 路径和值参数对,并返回形成的新 JSON 字符串 通过路径/值对更新输入 JSON。主要工作内容 区别仅在于它们如何处理创建新值和覆盖 预先存在的值。

功能如果已经存在,请覆盖?如果不存在,请创建?
json_insert()是的
json_replace()是的
json_set()是的是的

json_insert()、json_replace() 和 json_set() 函数始终 取奇数个参数。第一个参数始终是原始参数 要编辑的 JSON。后续参数与第一个参数成对出现 每对元素是路径,第二个元素是值 插入、替换或设置该路径。

编辑从左到右依次进行。由以下原因引起的更改 先前的编辑可能会影响后续编辑的路径搜索。

如果路径/值对的值是 SQLite TEXT 值,则它 通常作为带引号的 JSON 字符串插入,即使该字符串看起来 就像有效的 JSON 一样。但是,如果该值是另一个的结果 json 函数(例如 json() 或 json_array() 或 json_object()) 或者如果它是 -> 运算符的结果, 然后将其解释为 JSON,并作为 JSON 插入,保留所有 其下部结构。作为 ->> 运算符的结果的值始终被解释为 TEXT,甚至入为 JSON 字符串 如果它们看起来像有效的 JSON。

如果第一个 JSON 参数不是,则这些例程会引发错误 格式正确,或者如果任何 PATH 参数格式不正确,或者如果有 参数是一个 BLOB。

要将元素附加到数组的末尾,请使用 json_insert() 数组索引为“#”。例子:

  • json_insert('[1,2,3,4]','$[#]',99) → '[1,2,3,4,99]'
  • json_insert('[1,[2,3],4]','$[1][#]',99) → '[1,[2,3,99],4]'

其他示例:

  • json_insert('{"a":2,"c":4}', '$.a', 99) → '{"a":2,"c":4}'
  • json_insert('{"a":2,"c":4}', '$.e', 99) → '{"a":2,"c":4,"e":99}'
  • json_replace('{"a":2,"c":4}', '$.a', 99) → '{"a":99,"c":4}'
  • json_replace('{"a":2,"c":4}', '$.e', 99) → '{"a":2,"c":4}'
  • json_set('{"a":2,"c":4}', '$.a', 99) → '{"a":99,"c":4}'
  • json_set('{"a":2,"c":4}', '$.e', 99) → '{"a":2,"c":4,"e":99}'
  • json_set('{"a":2,"c":4}', '$.c', '[97,96]') → '{"a":2,"c":"[97,96]"}'
  • json_set('{"a":2,"c":4}', '$.c', json('[97,96]')) → '{"a":2,"c":[97,96]}'
  • json_set('{"a":2,"c":4}', '$.c', json_array(97,96)) → '{"a":2,"c":[97,96]}'

4.11. jsonb_insert()、jsonb_replace 和 jsonb_set()函数

jsonb_insert()、jsonb_replace()和 jsonb_set()函数的工作方式是 分别与 json_insert()、json_replace() 和 json_set() 相同, 除了“jsonb_”版本以二进制文件返回其结果 JSONB 格式。

4.12. json_object()函数

json_object()SQL 函数接受零对或多对参数 并返回由这些参数组成的格式正确的 JSON 对象。 每对的第一个参数是标签,第二个参数是 每对都是值。 如果 json_object()的任何参数是 BLOB,则会引发错误。

json_object()函数目前允许重复标签,而没有 投诉,尽管这可能会在将来的增强功能中发生变化。

具有 SQL 类型 TEXT 的参数,通常将其转换为带引号的 JSON 字符串,即使输入文本格式正确为 JSON。 但是,如果参数是另一个 JSON 的直接结果 函数或 -> 运算符(但不是 ->> 运算符), 然后将其视为 JSON 及其所有 JSON 类型信息 并保留了下部结构。这允许调用 json_object()和 json_array() 要嵌套。json() 函数还可以 用于强制将字符串识别为 JSON。

例子:

  • json_object('a',2,'c',4) → '{"a":2,"c":4}'
  • json_object('a',2,'c','{e:5}') → '{"a":2,"c":"{e:5}"}'
  • json_object('a',2,'c',json_object('e',5)) → '{"a":2,"c":{"e":5}}'

4.13. jsonb_object()函数

jsonb_object()函数的工作方式与 json_object() 函数类似 除了生成的对象以二进制 JSONB 格式返回。

4.14. json_patch()函数

json_patch(T,P) SQL 函数运行 RFC-7396 MergePatch 算法 对输入 T 应用补丁 P。返回 T 的修补副本。

MergePatch 可以添加、修改或删除 JSON 对象的元素, 因此,对于 JSON 对象,json_patch() 例程是通用的 替换 json_set() 和 json_remove()。但是,MergePatch 将 JSON 数组对象视为原子对象。MergePatch 不能附加到 数组,也不修改数组的单个元素。它只能插入, 替换或删除整个数组作为单个单元。因此,json_patch() 在处理包含数组的 JSON 时没有那么有用, 尤其是具有大量子结构的数组。

例子:

  • json_patch('{"a":1,"b":2}','{"c":3,"d":4}') → '{"a":1,"b":2,"c":3,"d":4}'
  • json_patch('{"a":[1,2],"b":2}','{"a":9}') → '{"a":9,"b":2}'
  • json_patch('{"a":[1,2],"b":2}','{"a":null}') → '{"b":2}'
  • json_patch('{"a":1,"b":2}','{"a":9,"b":null,"c":8}') → '{"a":9,"c":8}'
  • json_patch('{"a":{"x":1,"y":2},"b":3}','{"a":{"y":9},"c":8}') → '{"a":{"x":1,"y":9},"b":3,"c":8}'

4.15. jsonb_patch()函数

jsonb_patch() 函数的工作方式与 json_patch() 函数类似 除了修补后的 JSON 以二进制 JSONB 格式返回。

4.16. json_remove()数

json_remove(X,P,...) 函数采用单个 JSON 值作为其 第一个参数后跟零个或多个路径参数。 json_remove(X,P,...) 函数返回 包含所有元素的 X 参数的副本 由删除的路径参数标识。选择元素的路径 在 X 中找不到将被静默忽略。

移除从左到右依次进行。由以下原因引起的更改 先前的删除可能会影响后续参数的路径搜索。

如果调用 json_remove(X) 函数时没有路径参数, 然后它返回重新格式化的输入 X,其中包含多余的空格 删除。

如果第一个参数,则 json_remove()函数会抛出错误 不是格式正确的 JSON,或者如果任何后面的参数不是格式正确的 路径。

例子:

  • json_remove('[0,1,2,3,4]','$[2]') → '[0,1,3,4]'
  • json_remove('[0,1,2,3,4]','$[2]','$[0]') → '[1,3,4]'
  • json_remove('[0,1,2,3,4]','$[0]','$[2]') → '[1,2,4]'
  • json_remove('[0,1,2,3,4]','$[#-1]','$[0]') → '[1,2,3]'
  • json_remove('{"x":25,"y":42}') → '{"x":25,"y":42}'
  • json_remove('{"x":25,"y":42}','$.z') → '{"x":25,"y":42}'
  • json_remove('{"x":25,"y":42}','$.y') → '{"x":25}'
  • json_remove('{"x":25,"y":42}','$') → NULL

4.17. jsonb_remove()函数

jsonb_remove() 函数的工作方式与 json_remove() 函数类似 除了编辑后的 JSON 结果以二进制 JSONB 格式返回。

4.18. json_type()函数

json_type(X) 函数返回最外层元素的“类型” 的 X。json_type(X,P) 函数返回元素的“类型” 在 X 中,由路径 P 选择。json_type() 返回的“类型”是 以下 SQL 文本值之一: 'null', 'true', 'false', 'integer', 'real', 'text', 'array' 或 'object'。 如果 json_type(X,P) 中的路径 P 选择了不存在的元素 在 X 中,则此函数返回 NULL。

如果 json_type()函数的第一个参数为 格式不正确的 JSON 或 JSONB,或者它的第二个参数格式不正确 JSON 路径。

例子:

  • json_type('{"a":[2,3.5,true,false,null,"x"]}') → 'object'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$') → 'object'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a') → 'array'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]') → 'integer'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]') → 'real'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]') → 'true'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]') → 'false'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]') → 'null'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]') → 'text'
  • json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]') → NULL

4.19. json_valid()函数

如果参数 X 格式正确,则 json_valid(X,Y) 函数返回 1 JSON,如果 X 格式不正确,则返回 0。Y 参数是一个整数 位掩码,用于定义“格式正确”的含义。以下位 的 Y 目前定义:

  • 0x01→ 输入是严格符合规范 RFC-8259 JSON 的文本, 没有任何扩展名。
  • 0x02→ 输入是具有上述 JSON5 扩展名的 JSON 文本。
  • 0x04→ 输入是一个 BLOB,表面上看起来是 JSONB。
  • 0x08→ 输入是严格符合内部 JSONB 格式的 BLOB。

通过组合位,可以导出以下有用的 Y 值:

  • 1 → X 是 RFC-8259 JSON 文本
  • 2 → X 是 JSON5 文本
  • 4 → X 可能是 JSONB
  • 5 → X 是 RFC-8259 JSON 文本或 JSONB
  • 6 → X 是 JSON5 文本或 JSONB ← 这可能是您想要的值
  • 8 → X 严格符合 JSONB
  • 9 → X 是 RFC-8259 或严格符合 JSONB
  • 10 → X 是 JSON5 或严格符合 JSONB

Y 参数是可选的。如果省略,则默认为 1,这意味着 默认行为是仅当输入 X 为 严格符合 RFC-8259 JSON 文本,不带任何扩展名。这 使 json_valid() 的单参数版本与旧的 SQLite 版本,在添加对 JSON5 和 JSONB 的支持之前。

Y 参数中 0x04 位和 0x08 位的区别在于 0x04 只检查 BLOB 的外部包装,看看它是否表面上 看起来像 JSONB。这对于必须的目的来说已经足够了,而且速度非常快。 0x08位对 BLOB 的所有内部细节进行彻底检查。 0x08位所需的时间与 X 输入的大小呈线性关系,并且非常大 慢。大多数用途都建议使用 0x04 位。

如果您只是想知道一个值是否是以下之一的合理输入 其他 JSON 函数,Y 值 6 可能是您想要使用的。

任何小于 1 或大于 15 的 Y 值都会引发错误,因为 json_valid() 的最新版本。但是,json_valid() 的未来版本 可能会增强为接受超出此范围的标志值,具有新的 我们还没有想到的含义。

如果 json_valid() 的 X 或 Y 输入为 NULL,则函数 返回 NULL。

例子:

  • json_valid('{"x":35}') → 1
  • json_valid('{x:35}') → 0
  • json_valid('{x:35}',6) → 1
  • json_valid('{"x":35') → 0
  • json_valid(NULL) → NULL

4.20. json_quote() 函数

json_quote(X) 函数转换 SQL 值 X(数字或 string) 转换为其对应的 JSON 表示形式。如果 X 是 JSON 值 由另一个 JSON 函数返回,则此函数是 no-op。

例子:

  • json_quote(3.14159) → 3.14159
  • json_quote('verdant') → '"verdant"'
  • json_quote('[1]') → '"[1]"'
  • json_quote(json('[1]')) → '[1]'
  • json_quote('[1,') → '"[1,"'

4.21. 数组和对象聚合函数

json_group_array(X) 函数是一个聚合 SQL 函数,返回一个 JSON 数组 由聚合中的所有 X 值组成。 同样,json_group_object(NAME,VALUE) 函数返回一个 JSON 对象 由聚合中的所有 NAME/VALUE 对组成。 “jsonb_”变体是相同的,只是它们返回 结果为二进制 JSONB 格式。

4.22. json_each()和 json_tree()表值函数

json_each(X) 和 json_tree(X) 表值函数遍历 JSON 值作为其第一个参数提供,并为每个参数返回一行 元素。json_each(X) 功能仅引导直系子女 顶级数组或对象, 或者只是顶级元素本身,如果顶级 元素是基元值。 json_tree(X) 函数递归遍历 从顶级元素开始的 JSON 子结构。

json_each(X,P) 和 json_tree(X,P) 函数的工作方式与 他们的单参数对应物,除了他们处理元素 由路径 P 标识为顶级元素。

json_each() 和 json_tree() 返回的表的架构为 如下:

CREATE TABLE json_tree(
    key ANY,             -- key for current element relative to its parent
    value ANY,           -- value for the current element
    type TEXT,           -- 'object','array','string','integer', etc.
    atom ANY,            -- value for primitive types, null for array & object
    id INTEGER,          -- integer ID for this element
    parent INTEGER,      -- integer ID for the parent of this element
    fullkey TEXT,        -- full path describing the current element
    path TEXT,           -- path to the container of the current row
    json JSON HIDDEN,    -- 1st input parameter: the raw JSON
    root TEXT HIDDEN     -- 2nd input parameter: the PATH at which to start
);

“key”列是 JSON 数组元素的整数数组索引 以及 JSON 对象元素的文本标签。键列是 在所有其他情况下为 NULL。

“atom”列是原元元素对应的 SQL 值 - JSON 数组和对象以外的元素。“atom”列为 NULL 用于 JSON 数组或对象。“value” 列与 “atom”列用于原始 JSON 元素,但采用文本 JSON 值 用于数组和对象。

“type”列是从 ('null', 'true', 'false', 'integer', 'real', 'text', 'array', 'object') 当前 JSON 元素。

“id”列是一个整数,用于标识特定的 JSON 元素 在完整的 JSON 字符串中。“id”整数是内部内务管理 number,其计算方法可能会在将来的版本中发生变化。这 唯一可以保证的是每一行的“id”列都不同。

对于 json_each(),“parent”列始终为 NULL。 对于 json_tree(), “parent”列是当前父项的“id”整数 元素,或顶级 JSON 元素或标识的元素的 NULL 通过第二个参数中的根路径。

“fullkey”列是唯一标识当前 原始 JSON 字符串中的 row 元素。完整的钥匙 即使有替代起点,也会返回 True 顶级元素 由“root”参数提供。

“path”列是保存数组或对象容器的路径 当前行,或当前行的路径,如果 迭代从基元类型开始,因此仅提供单个 输出行。

4.22.1. 使用 json_each()和 json_tree()的示例

假设表“CREATE TABLE user(name,phone)”存储零或 更多电话号码作为 user.phone 字段中的 JSON 数组对象。 要查找拥有任何带有 704 区号的电话号码的所有用户:

SELECT DISTINCT user.name
  FROM user, json_each(user.phone)
 WHERE json_each.value LIKE '704-%';

现在假设 user.phone 字段包含纯文本,如果用户 只有一个电话号码和一个 JSON 数组(如果用户有多个电话号码) 电话号码。提出了同样的问题:“哪些用户有电话号码 在704区号中?但是现在只能调用 json_each() 函数 对于自 json_each()以来拥有两个或更多电话号码的用户 需要格式正确的 JSON 作为其第一个参数:

SELECT name FROM user WHERE phone LIKE '704-%'
UNION
SELECT user.name
  FROM user, json_each(user.phone)
 WHERE json_valid(user.phone)
   AND json_each.value LIKE '704-%';

考虑使用“CREATE TABLE big(json JSON)”的不同数据库。 要查看数据的完整逐行分解,请执行以下操作:

SELECT big.rowid, fullkey, value
  FROM big, json_tree(big.json)
 WHERE json_tree.type NOT IN ('object','array');

在前面的“type NOT IN ('object','array')”项中 WHERE 子句禁止容器,只允许通过叶元素。 可以通过以下方式实现相同的效果:

SELECT big.rowid, fullkey, atom
  FROM big, json_tree(big.json)
 WHERE atom IS NOT NULL;

假设 BIG 表中的每个条目都是一个 JSON 对象 带有唯一标识符的“$.id”字段 以及可以是深度嵌套对象的“$.partlist”字段。 您希望查找包含 或更多引用 UUID '6fa5181e-5721-11e5-a04e-57f3d7b32808' 在其“$.partlist”中。

SELECT DISTINCT json_extract(big.json,'$.id')
  FROM big, json_tree(big.json, '$.partlist')
 WHERE json_tree.key='uuid'
   AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/560645.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

程序员自由创业周记#32:新产品构思

程序员自由创业周记#32:新产品构思 新作品 我时常把自己看做一位木匠,有点手艺,能做一些作品养活自己。而 加一、Island Widgets、Nap 就是我的作品。 接下来在持续维护迭代的同时,要开启下一个作品的创造了。 其实早在2022的1…

【C++初阶】List使用特性及其模拟实现

1. list的介绍及使用 1.1 list的介绍 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前…

(2022级)成都工业学院数据库原理及应用实验五: SQL复杂查询

写在前面 1、基于2022级软件工程/计算机科学与技术实验指导书 2、成品仅提供参考 3、如果成品不满足你的要求,请寻求其他的途径 运行环境 window11家庭版 Navicat Premium 16 Mysql 8.0.36 实验要求 在实验三的基础上完成下列查询: 1、查询医生…

漆包线行业你了解多少?专业漆包线行业MES生产管理系统

今天就说说漆包线行业,漆包线是工业电机(包括电动机和发电机)、变压器、电工仪表、电力及电子元器件、电动工具、家用电器、汽车电器等用来绕制电磁线圈的主要材料。 漆包线上游是铜杆行业,下游是各种消费终端,主要是电…

[大模型]Qwen-Audio-chat FastApi 部署调用

Qwen-Audio-chat FastApi 部署调用 Qwen-Audio 介绍 Qwen-Audio 是阿里云研发的大规模音频语言模型(Large Audio Language Model)。Qwen-Audio 可以以多种音频 (包括说话人语音、自然音、音乐、歌声)和文本作为输入,并以文本作为…

Linux-用户管理类命令实训

查看根目录下有哪些内容 进入/tmp目录,以自己的学号建一个目录,并进入该目录 像是目前所在的目录 在当前目录下,建立权限为741的目录test1 在目录test1下建立目录test2/test3/test4 进入test2,删除目录test3/test4 (7&…

Python实现在线翻译工具

Python实现在线翻译工具 使用Python的内置的标准库tkinter和webbrowser,实现一个简单Python在线翻译工具。 tkinter库用来创建一个图形用户界面(GUI),webbrowser库用来打开网页。 webbrowser 是 Python 的一个标准库&#xff0…

7.MMD 法线贴图的设置与调教

前期准备 人物 导入温迪模型导入ray.x和ray_controler.pmx导入天空盒time of day调成模型绘制顺序,将天空盒调到最上方给温迪模型添加main.fx材质在自发光一栏,给天空盒添加time of lighting材质 打开材质里的衣服,发现只有一个衣服文件 …

SpringBoot集成FTP

1.加入核心依赖 <dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.8.0</version></dependency> 完整依赖 <dependencies><dependency><groupId>org.springfra…

什么是时间序列分析

时间序列分析是现代计量经济学的重要内容&#xff0c;广泛应用于经济、商业、社会问题研究中&#xff0c;在指标预测中具有重要地位&#xff0c;是研究统计指标动态特征和周期特征及相关关系的重要方法。 一、基本概念 经济社会现象随着时间的推移留下运行轨迹&#xff0c;按…

Linux网络编程--网络传输

Linux网络编程--网络传输 Linux网络编程TCP/IP网络模型网络通信的过程局域网通信跨网络通信&#xff1a;问题总结&#xff1a; Linux网络编程 TCP/IP网络模型 发送方&#xff08;包装&#xff09;&#xff1a; 应用层&#xff1a;HTTP HTTPS SSH等 —> 包含数据&#xff0…

二维码门楼牌管理应用平台建设:助力场所整改与消防安全

文章目录 前言一、二维码门楼牌管理应用平台的构建背景二、二维码门楼牌管理应用平台在场所整改中的作用三、二维码门楼牌管理应用平台的意义与价值四、二维码门楼牌管理应用平台的未来展望 前言 随着城市管理的日益精细化&#xff0c;二维码门楼牌管理应用平台的建设成为了提…

正则表达式中 “$” 并不是表示 “字符串结束”

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 作者&#xff1a;Seth Larson 译者&#xff1a;豌豆花下猫Python猫 英文&#xff1a;Regex character “$” doesnt mean “end-of-string” 转载请保留作者及译者信息&#xff01; 这篇文章写一写我最近在用 Python …

【Django】学习笔记

文章目录 [toc]MVC与MTVMVC设计模式MTV设计模式 Django下载Django工程创建与运行创建工程运行工程 子应用创建与注册安装创建子应用注册安装子应用 数据模型ORM框架模型迁移 Admin站点修改语言和时区设置管理员账号密码模型注册显示对象名称模型显示中文App显示中文 视图函数与…

英文面试中如何回答为什么离职?柯桥英语口语学校

面试中&#xff0c;面试官可能会问到如下问题&#xff1a; 1.Why are you looking for another job? 你为什么要换工作&#xff1f; 2.May I ask why you left the company? 可以问一下你为什么要离开那家公司吗&#xff1f; 3.What’s the reason for you to leave your …

基于通达信---做T专用算法

什么是做T? 股票做T是股票市场中常见的一种投资策略,也就是股票进行T+0操作,通过当天买进的股票,在当天卖出,是股市中常见的一种超短线的操作。其中T就是指交易日,利用交易日中的股票涨跌来赚取差价。股票做T常见的类型就是正T和倒T。 1、正T 股票做正t就是指先买后卖,…

历史融资额高达 2.44 亿美元的 Monad,是何方神圣?

以并行 EVM 为特点的 Monad&#xff0c;又一个具备竞争力的“以太坊杀手” 在今年 4 月初&#xff0c;Monad Labs&#xff08;Monad 的开发团队&#xff09; 获得了一笔由 Paradigm 领投的高达 2.25 亿美元的巨额融资&#xff0c;本轮融资的其他投资者还包括&#xff1a; Elec…

云服务器需要多少流量?评估支持最大并发量?

一 需要购买多大的流量&#xff1f; 项目上线时&#xff0c;我们需要购买多大的流量的带宽&#xff1f;支持多少设备&#xff08;支持多少并发量&#xff0c;在设计阶段会计算&#xff09;&#xff1f;作为架构师我们必须清楚与明确。 二 清楚服务器的流量计算 常见的云服务主机…

Android安卓写入WIFI热点自动连接NDEF标签

本示例使用的发卡器&#xff1a;Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/网址/海报-淘宝网 (taobao.com) package com.usbreadertest;import android.os.Bundle; import android.view.MenuItem; import android.view.View; import android.widget.EditText; impo…

机器学习系统的设计

1.混淆矩阵 混淆矩阵作用就是看一看在测试集样本集中&#xff1a; 真实值是 正例 的样本中&#xff0c;被分类为 正例 的样本数量有多少&#xff0c;这部分样本叫做真正例&#xff08;TP&#xff0c;True Positive&#xff09;&#xff0c;预测为真&#xff0c;实际为真真实值…