我已阅读过文档,似乎没有明显的方法可以执行ALTER TABLE ... ALTER COLUMN ... USING
语句直接将json
类型列转换为hstore
类型。没有可用的功能(我知道)可以执行演员表。
我的下一个最佳选择是创建一个hstore
类型的新列,使用一些外部工具将我的JSON数据复制到该新列,删除旧json
列并重命名新{ {1}}列为旧列的名称。
有更好的方法吗?
到目前为止我所拥有的是:
hstore
$ CREATE TABLE blah (unstructured_data JSON); $ ALTER TABLE blah ALTER COLUMN unstructured_data TYPE hstore USING CAST(unstructured_data AS hstore);
答案 0 :(得分:9)
不幸的是,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);
答案 1 :(得分:1)
存在重复键的“陷阱”-由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
中,并且不能保证保留哪些密钥:
通常,是键的 first 实例,但这是可能会更改的实现细节。
始终保留有效的操作价值的简单快捷选项:转换前强制转换为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。