我读过的文档,并似乎有执行ALTER TABLE ... ALTER COLUMN ... USING
语句来json
类型列直接转换为hstore
类型没有明显的方式。有没有可用的功能(即我所知道的)来执行转换。
我有一个最好的方法是创建类型hstore
的新列,我的JSON数据复制到使用一些外部工具,新列,删除旧json
列,并重新命名新hstore
列老列的名称。
有没有更好的办法?
我至今是:
$ CREATE TABLE blah (unstructured_data JSON);
$ ALTER TABLE blah ALTER COLUMN unstructured_data
TYPE hstore USING CAST(unstructured_data AS hstore);
ERROR: cannot cast type json to hstore
不幸的是,PostgreSQL并不让各类USING
的ALTER TABLE ... SET DATA TYPE ...
子句中的表达式(f.ex.子查询是不允许的)。
但是,你可以写克服这个功能,你只需要决定如何处理先进的类型做(在对象的值),如数组和对象。下面是一个例子,它只是将它们转换成字符串:
CREATE OR REPLACE FUNCTION my_json_to_hstore(json)
RETURNS hstore
IMMUTABLE
STRICT
LANGUAGE sql
AS $func$
SELECT hstore(array_agg(key), array_agg(value))
FROM json_each_text($1)
$func$;
在这之后,你可以在你的ALTER TABLE
使用,如:
ALTER TABLE blah
ALTER COLUMN unstructured_data
SET DATA TYPE hstore USING my_json_to_hstore(unstructured_data);
有“陷阱”重复键 - (!)双方json
和hstore
输入允许的,但不幸的是解决不同。考虑这个例子值:
json '{"double_key":"key1","foo":null,"double_key":"key2"}'
在json
,“double_key实际上是 'KEY2'。 The manual:
因为
json
类型存储输入文本的精确副本,它将保留JSON对象中键的顺序标记之间语义无关紧要的空格,以及。此外,如果该值内的JSON对象包含相同的键不止一次,所有的键/值对被保留。 (处理功能考虑的最后一个值作为操作之一。)
大胆重点煤矿。
在hstore
,然而,键/值对的顺序相同,“double_key”可能有效地将“KEY1”。 The manual:
在
hstore
每个键都是唯一的。如果声明hstore
有重复键,只有一个会被存储在hstore
并没有保证哪个将被保留:
通常情况下,一个关键的第一个实例,但是这是一个实现细节可能会改变。
一个简单,快速的选择始终保持有效,手术值:铸转换之前jsonb
。 The manual again:
[...]
jsonb
不保留空白,不保留对象键的顺序,并不会保留重复的对象键。如果输入指定重复键,只有最后一个值保持。
修改@pozs's conversion function:
CREATE OR REPLACE FUNCTION json2hstore(json)
RETURNS hstore AS
$func$
SELECT hstore(array_agg(key), array_agg(value))
FROM jsonb_each_text($1::jsonb) -- !
$func$ LANGUAGE sql IMMUTABLE STRICT;
需要的Postgres 9.4或更高版本。 Postgres的9.3有json
类型,但不jsonb
,但。无操作在PL / V8可能是替代那里,就像@jpmc mentioned。