将列类型从 JSONB 更改为 JSON
Change column type from JSONB to JSON
我知道大多数用户都在寻找 jsonb
类型,其中检索值的速度比 json
类型快得多。尽管如此,我仍然需要键值中的顺序,到目前为止,我认为实现此目的的最佳方法是将我的列类型迁移到 json
。
我尝试了以下方法:
ALTER TABLE table_name
ALTER COLUMN jsonb_colum TYPE json
和
ALTER TABLE table_name
ALTER COLUMN jsonb_colum TYPE json
USING jsonb_colum::json
在这两种情况下,我都会收到此错误:
ERROR: Operator class "jsonb_path_ops" does not accept data type json.
我也尝试过使用 USING
子句和如下表达式:
ALTER TABLE table_name
ALTER COLUMN jsonb_column TYPE json
USING jsonb_column::to_json(jsonb_colum)
但也没有运气,出现以下错误:
ERROR: Type "to_json" does not exist
有什么解决方法可以实现我的愿望吗?
我正在使用 PostgreSQL 13.3 (Debian 13.3-1.pgdg100+1) 64-bit
jsonb_path_ops
is an operator class 用于 GIN 索引。喜欢:
CREATE INDEX foo ON table_name USING gin (jsonb_column jsonb_path_ops);
这种索引的存在会准确地产生您的第一条错误消息。在更改列类型之前,您需要删除任何此类索引 - 使用第一个有效的 ALTER TABLE
语句。
但是,这样一个索引的存在将表明需要支持这些 jsonb
运算符中的一个或多个:@>
、@?
、@@
。如果是这样,请考虑在转换为 json
之后创建一个 expression index 来替换旧的。喜欢:
CREATE INDEX foo ON table_name USING gin ((now_json_column::jsonb) jsonb_path_ops);
(需要括号。)
那么仍然支持这样的查询(即使成本略高):
SELECT * FROM table_name
WHERE now_json_column::jsonb @> '{"some_key": "some_val"}';
相关:
- Index for finding an element in a JSON array
此外,请注意 json
缺少的基本等式和不等式运算符。参见:
- How to query a json column for empty objects?
可以使用查询从现有 jsonb 列更新新制作的 json 格式化列,并按所需顺序 select 取出键。下面是一个示例 table、数据集和更新查询。
create table crayons (
id serial,
color_json json,
color_jsonb jsonb,
primary key (id))
ugautil=> \d crayons
Table "public.crayons"
Column | Type | Collation | Nullable | Default
-------------+---------+-----------+----------+-----------------------------------
id | integer | | not null | nextval('crayons_id_seq'::regclass)
color_json | json | | |
color_jsonb | jsonb | | |
Indexes:
"crayons_pkey" PRIMARY KEY, btree (id)
color_json 列将保留与原始数据中相同的文本
文件。 color_jsonb 列不会保留键顺序,
重复键、额外空格等
前5行数据:
ugautil=> select color_json from crayons order by id limit 5;
-----------------------------------------------------------
{"hex":"#EFDECD","name":"Almond","rgb":"(239, 222, 205)"}
{"hex":"#CD9575","name":"Antique Brass","rgb":"(205, 149, 117)"}
{"hex":"#FDD9B5","name":"Apricot","rgb":"(253, 217, 181)"}
{"hex":"#78DBE2","name":"Aquamarine","rgb":"(120, 219, 226)"}
{"hex":"#87A96B","name":"Asparagus","rgb":"(135, 169, 107)"}
当我们 select 来自 jsonb 列的相同数据时,请注意它更改了键顺序。
名称在 rgb
之后
ugautil=> select color_jsonb from crayons order by id limit 5;
-------------------------------------------------------------
{"hex": "#EFDECD", "rgb": "(239, 222, 205)", "name": "Almond"}
{"hex": "#CD9575", "rgb": "(205, 149, 117)", "name": "Antique Brass"}
{"hex": "#FDD9B5", "rgb": "(253, 217, 181)", "name": "Apricot"}
{"hex": "#78DBE2", "rgb": "(120, 219, 226)", "name": "Aquamarine"}
{"hex": "#87A96B", "rgb": "(135, 169, 107)", "name": "Asparagus"}
我们可以使用函数 to_json() 将列 color_jsonb 转换回 json 格式,但它不会
return 原始密钥排序。
ugautil=> select to_json(color_jsonb) from crayons limit 5;
----------------------------------------------------------------
{"hex": "#EFDECD", "rgb": "(239, 222, 205)", "name": "Almond"}
{"hex": "#CD9575", "rgb": "(205, 149, 117)", "name": "Antique Brass"}
{"hex": "#FDD9B5", "rgb": "(253, 217, 181)", "name": "Apricot"}
{"hex": "#78DBE2", "rgb": "(120, 219, 226)", "name": "Aquamarine"}
{"hex": "#87A96B", "rgb": "(135, 169, 107)", "name": "Asparagus"}
但是我们可以挑选出单独的密钥并对其进行格式化。
ugautil=> select format('{"hex": %s,"name": %s, "rgb": %s}',
color_jsonb->'hex',color_jsonb->'name', color_jsonb->'rgb')
from crayons limit 5;
----------------------------------------------------------------
{"hex": "#EFDECD","name": "Almond", "rgb": "(239, 222, 205)"}
{"hex": "#CD9575","name": "Antique Brass", "rgb": "(205, 149, 117)"}
{"hex": "#FDD9B5","name": "Apricot", "rgb": "(253, 217, 181)"}
{"hex": "#78DBE2","name": "Aquamarine", "rgb": "(120, 219, 226)"}
{"hex": "#87A96B","name": "Asparagus", "rgb": "(135, 169, 107)"}
更改 table 以创建一个新列来保存您想要的 json 类型
ugautil=> alter table crayons add column color_json2 json;
用来自 jsonb 的 selects 的查询更新 table
列,并按您想要的顺序格式化键,并使用它
更新新的 color_json2 列。
with subquery as (
select id,
format('{"hex": %s,"name": %s, "rgb": %s}',
color_jsonb->'hex',color_jsonb->'name',
color_jsonb->'rgb') as "color_json2_fmt"
from crayons
)
update crayons
set color_json2 = subquery.color_json2_fmt::json
from subquery
where crayons.id = subquery.id;
ugautil=> select color_json2 from crayons limit 5;
color_json2
---------------------------------------------------------------
{"hex": "#EFDECD","name": "Almond", "rgb": "(239, 222, 205)"}
{"hex": "#CD9575","name": "Antique Brass", "rgb": "(205, 149, 117)"}
{"hex": "#FDD9B5","name": "Apricot", "rgb": "(253, 217, 181)"}
{"hex": "#78DBE2","name": "Aquamarine", "rgb": "(120, 219, 226)"}
{"hex": "#87A96B","name": "Asparagus", "rgb": "(135, 169, 107)"}
Explanation of JSONB introduced by PostgreSQL
updating table rows in postgres using subquery
请使用以下查询将 postgresql 中的现有列更改为 jsonb
ALTER TABLE schema_name.table_name
ALTER COLUMN column_name TYPE jsonb USING column_name::jsonb;
在上面的查询中,如果您使用 pgAdmin4,column_name 必须突出显示。否则当 运行 这个查询时你会得到错误。
我知道大多数用户都在寻找 jsonb
类型,其中检索值的速度比 json
类型快得多。尽管如此,我仍然需要键值中的顺序,到目前为止,我认为实现此目的的最佳方法是将我的列类型迁移到 json
。
我尝试了以下方法:
ALTER TABLE table_name
ALTER COLUMN jsonb_colum TYPE json
和
ALTER TABLE table_name
ALTER COLUMN jsonb_colum TYPE json
USING jsonb_colum::json
在这两种情况下,我都会收到此错误:
ERROR: Operator class "jsonb_path_ops" does not accept data type json.
我也尝试过使用 USING
子句和如下表达式:
ALTER TABLE table_name
ALTER COLUMN jsonb_column TYPE json
USING jsonb_column::to_json(jsonb_colum)
但也没有运气,出现以下错误:
ERROR: Type "to_json" does not exist
有什么解决方法可以实现我的愿望吗?
我正在使用 PostgreSQL 13.3 (Debian 13.3-1.pgdg100+1) 64-bit
jsonb_path_ops
is an operator class 用于 GIN 索引。喜欢:
CREATE INDEX foo ON table_name USING gin (jsonb_column jsonb_path_ops);
这种索引的存在会准确地产生您的第一条错误消息。在更改列类型之前,您需要删除任何此类索引 - 使用第一个有效的 ALTER TABLE
语句。
但是,这样一个索引的存在将表明需要支持这些 jsonb
运算符中的一个或多个:@>
、@?
、@@
。如果是这样,请考虑在转换为 json
之后创建一个 expression index 来替换旧的。喜欢:
CREATE INDEX foo ON table_name USING gin ((now_json_column::jsonb) jsonb_path_ops);
(需要括号。)
那么仍然支持这样的查询(即使成本略高):
SELECT * FROM table_name
WHERE now_json_column::jsonb @> '{"some_key": "some_val"}';
相关:
- Index for finding an element in a JSON array
此外,请注意 json
缺少的基本等式和不等式运算符。参见:
- How to query a json column for empty objects?
可以使用查询从现有 jsonb 列更新新制作的 json 格式化列,并按所需顺序 select 取出键。下面是一个示例 table、数据集和更新查询。
create table crayons (
id serial,
color_json json,
color_jsonb jsonb,
primary key (id))
ugautil=> \d crayons
Table "public.crayons"
Column | Type | Collation | Nullable | Default
-------------+---------+-----------+----------+-----------------------------------
id | integer | | not null | nextval('crayons_id_seq'::regclass)
color_json | json | | |
color_jsonb | jsonb | | |
Indexes:
"crayons_pkey" PRIMARY KEY, btree (id)
color_json 列将保留与原始数据中相同的文本 文件。 color_jsonb 列不会保留键顺序, 重复键、额外空格等
前5行数据:
ugautil=> select color_json from crayons order by id limit 5;
-----------------------------------------------------------
{"hex":"#EFDECD","name":"Almond","rgb":"(239, 222, 205)"}
{"hex":"#CD9575","name":"Antique Brass","rgb":"(205, 149, 117)"}
{"hex":"#FDD9B5","name":"Apricot","rgb":"(253, 217, 181)"}
{"hex":"#78DBE2","name":"Aquamarine","rgb":"(120, 219, 226)"}
{"hex":"#87A96B","name":"Asparagus","rgb":"(135, 169, 107)"}
当我们 select 来自 jsonb 列的相同数据时,请注意它更改了键顺序。 名称在 rgb
之后ugautil=> select color_jsonb from crayons order by id limit 5;
-------------------------------------------------------------
{"hex": "#EFDECD", "rgb": "(239, 222, 205)", "name": "Almond"}
{"hex": "#CD9575", "rgb": "(205, 149, 117)", "name": "Antique Brass"}
{"hex": "#FDD9B5", "rgb": "(253, 217, 181)", "name": "Apricot"}
{"hex": "#78DBE2", "rgb": "(120, 219, 226)", "name": "Aquamarine"}
{"hex": "#87A96B", "rgb": "(135, 169, 107)", "name": "Asparagus"}
我们可以使用函数 to_json() 将列 color_jsonb 转换回 json 格式,但它不会 return 原始密钥排序。
ugautil=> select to_json(color_jsonb) from crayons limit 5;
----------------------------------------------------------------
{"hex": "#EFDECD", "rgb": "(239, 222, 205)", "name": "Almond"}
{"hex": "#CD9575", "rgb": "(205, 149, 117)", "name": "Antique Brass"}
{"hex": "#FDD9B5", "rgb": "(253, 217, 181)", "name": "Apricot"}
{"hex": "#78DBE2", "rgb": "(120, 219, 226)", "name": "Aquamarine"}
{"hex": "#87A96B", "rgb": "(135, 169, 107)", "name": "Asparagus"}
但是我们可以挑选出单独的密钥并对其进行格式化。
ugautil=> select format('{"hex": %s,"name": %s, "rgb": %s}',
color_jsonb->'hex',color_jsonb->'name', color_jsonb->'rgb')
from crayons limit 5;
----------------------------------------------------------------
{"hex": "#EFDECD","name": "Almond", "rgb": "(239, 222, 205)"}
{"hex": "#CD9575","name": "Antique Brass", "rgb": "(205, 149, 117)"}
{"hex": "#FDD9B5","name": "Apricot", "rgb": "(253, 217, 181)"}
{"hex": "#78DBE2","name": "Aquamarine", "rgb": "(120, 219, 226)"}
{"hex": "#87A96B","name": "Asparagus", "rgb": "(135, 169, 107)"}
更改 table 以创建一个新列来保存您想要的 json 类型
ugautil=> alter table crayons add column color_json2 json;
用来自 jsonb 的 selects 的查询更新 table 列,并按您想要的顺序格式化键,并使用它 更新新的 color_json2 列。
with subquery as (
select id,
format('{"hex": %s,"name": %s, "rgb": %s}',
color_jsonb->'hex',color_jsonb->'name',
color_jsonb->'rgb') as "color_json2_fmt"
from crayons
)
update crayons
set color_json2 = subquery.color_json2_fmt::json
from subquery
where crayons.id = subquery.id;
ugautil=> select color_json2 from crayons limit 5;
color_json2
---------------------------------------------------------------
{"hex": "#EFDECD","name": "Almond", "rgb": "(239, 222, 205)"}
{"hex": "#CD9575","name": "Antique Brass", "rgb": "(205, 149, 117)"}
{"hex": "#FDD9B5","name": "Apricot", "rgb": "(253, 217, 181)"}
{"hex": "#78DBE2","name": "Aquamarine", "rgb": "(120, 219, 226)"}
{"hex": "#87A96B","name": "Asparagus", "rgb": "(135, 169, 107)"}
Explanation of JSONB introduced by PostgreSQL
updating table rows in postgres using subquery
请使用以下查询将 postgresql 中的现有列更改为 jsonb
ALTER TABLE schema_name.table_name
ALTER COLUMN column_name TYPE jsonb USING column_name::jsonb;
在上面的查询中,如果您使用 pgAdmin4,column_name 必须突出显示。否则当 运行 这个查询时你会得到错误。