在 Postgres 9.3+ 中将 JSON 投射到 HSTORE?

Cast JSON to HSTORE in Postgres 9.3+?

我已阅读文档,似乎没有明确的方法来执行 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 不允许在 ALTER TABLE ... SET DATA TYPE ...USING 子句中使用所有类型的表达式(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()
$func$;

之后,您可以在 ALTER TABLE 中使用它,例如:

ALTER TABLE blah
  ALTER COLUMN unstructured_data
  SET DATA TYPE hstore USING my_json_to_hstore(unstructured_data);

重复键 有 "trap" - jsonhstore 输入都允许,但不幸的是解决方式不同(!)。考虑这个示例值:

json '{"double_key":"key1","foo":null,"double_key":"key2"}'

json中,'double_key实际上是'key2'The manual:

Because the json type stores an exact copy of the input text, it will preserve semantically-insignificant white space between tokens, as well as the order of keys within JSON objects. Also, if a JSON object within the value contains the same key more than once, all the key/value pairs are kept. (The processing functions consider the last value as the operative one.)

大胆强调我的。

hstore中,然而,对于相同顺序的key/value对,'double_key'可能 实际上是 'key1'The manual:

Each key in an hstore is unique. If you declare an hstore with duplicate keys, only one will be stored in the hstore and there is no guarantee as to which will be kept:

通常,第一个 键实例,但这是一个可能会更改的实现细节。

始终保留有效的操作值的简单而快速的选项:转换前转换为jsonbThe manual again:

[...] jsonb does not preserve white space, does not preserve the order of object keys, and does not keep duplicate object keys. If duplicate keys are specified in the input, only the last value is kept.

修改

CREATE OR REPLACE FUNCTION json2hstore(json)
  RETURNS hstore AS
$func$
  SELECT hstore(array_agg(key), array_agg(value))
  FROM   jsonb_each_text(::jsonb)  -- !
$func$ LANGUAGE sql IMMUTABLE STRICT;

需要 Postgres 9.4 或更高版本。 Postgres 9.3 有 json 类型,但还没有 jsonb。 PL/v8 中的空操作可能是替代方案,例如 .