PostGreSQL数据库提供了JSON和JSONB数据类型,用来存储JSON(JavaScript Object Notation)数据;同时,PG数据库也提供了一系列内置函数,用来JSON和JSONB数据类型。
JSON和JSONB数据类型可以接收相同的值作为输入,主要的差别在于读写时的效率。
json 数据类型存储输入文本的精确拷贝,处理函数必须在每个执行上重新解析; 而jsonb数据以分解的二进制格式存储, 这使得它由于添加了转换机制而在输入上稍微慢些,但是在处理上明显更快, 因为不需要重新解析。jsonb也支持索引,这也是一个明显的优势。
因为json类型存储输入文本的精确拷贝,它将保存令牌间语义上无关紧要的空格, 和JSON对象中键的顺序。另外,如果值中的一个JSON对象多次包含相同的键, 那么保存所有的键/值对。(处理函数将最后一个值当做操作值。)相比之下, jsonb不保存空格,也不保存对象键的顺序,并且不保存重复对象键。 如果在输入中指定了重复的键,那么只保存最后一个值。
通常,大多数应用更喜欢存储JSON数据为jsonb,除非有很专业的需要, 比如传统假设对象键的顺序。
例如:我们创建两张表tb_json、tb_jsonb,分别以JSON和JSONB数据类型存储一组相同的输入值。
create TABLE myschema.tb_json(
j_id INTEGER NOT NULL,
j_val JSON,
PRIMARY KEY (j_id)
);
create TABLE myschema.tb_jsonb(
j_id INTEGER NOT NULL,
j_val JSONB,
PRIMARY KEY (j_id)
);
表结构如下所示,
那么,在PostGreSQL数据库中,如何通过SQL语句来构造JSON数据呢?
JSON数据类型的输入/输出语法是在RFC 7159中指定的。
下列都是有效的 json(或jsonb)表达式:
-- 简单的标量/原始值
-- 原始值可以是数字、加引号的字符串、true、false或null
SELECT '5'::json;
-- 零个或者多个元素的数组 (元素不需要是相同的类型)
SELECT '[1, 2, "foo", null]'::json;
-- 包含键/值对的对象
-- 注意对象的键必须总是加双引号的字符串
SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;
--数组和对象可以任意的嵌套
SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json;
当输入一个JSON值并且然后没有任何处理的打印时, json输出和输入相同的文本,而jsonb没有保存语义上无关紧要的细节, 如空格。例如:
SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
json
-------------------------------------------------
{"bar": "baz", "balance": 7.77, "active":false}
(1 row)
SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
jsonb
--------------------------------------------------
{"bar": "baz", "active": false, "balance": 7.77}
(1 row)
下面构造一条复杂的JSON数据,然后分别插入一条数据,通过explain来查看执行效率,
SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json
将其插入到数据表中,
①插入到tb_json数据表;
--添加到tb_json
EXPLAIN
INSERT INTO myschema.tb_json(j_id,j_val)
VALUES(1,'{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json)
②插入到tb_jsonb数据表,
--添加到tb_jsonb
EXPLAIN
INSERT INTO myschema.tb_jsonb(j_id,j_val)
VALUES(1,'{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::jsonb);