我正在测试Postgresql 9.4 beta2。我想知道是否可以在嵌入式json对象上创建唯一索引?
我创建了一个表名products
:
CREATE TABLE products (oid serial primary key, data jsonb)
现在,我尝试将json对象插入数据列。
{
"id": "12345",
"bags": [
{
"sku": "abc123",
"price": 0,
},
{
"sku": "abc123",
"price": 0,
}
]
}
但是,我希望sku
行李袋是唯一的。这意味着json无法插入到产品表中,因为在这种情况下sku
不是唯一的。
我尝试创建一个如下所示的唯一索引,但它失败了。
CREATE UNIQUE INDEX product_sku_index ON products( (data->'bags'->'sku') )
有什么建议吗?
答案 0 :(得分:4)
由于多种原因,您在表达式上创建UNIQUE INDEX
的尝试肯定会失败。
<击> CREATE UNIQUE INDEX product_sku_index ON products( (data->'bags'->'sku') )
击>
第一个也是最微不足道的......
<击> data->'bags'->'sku'
击>
不 引用任何。您可以使用
data->'bags'->0->>'sku'
或更短:
data#>>'{bags,0,sku}'
但该表达式只返回数组的第一个值
你的定义:&#34;我希望袋子的sku是独一无二的&#34; ..目前还不清楚。您希望sku
的值是唯一的吗?在一个JSON对象中或data
列中的所有json对象中?或者您是否希望将数组限制为具有sku
?
无论哪种方式,这些目标都不能用简单的UNIQUE
索引来实现。
如果您希望sku
值在data->'bags'
中的所有json数组中都是唯一的,则有一种方法。将数组unnest并将所有单独的sku
值写入具有唯一(或PK)约束的简单辅助表中的单独行:
CREATE TABLE prod_sku(sku text PRIMARY KEY); -- PK enforces uniqueness
此表可能有助于其他目的 这是一个完整的代码示例,用于与普通Postgres数组非常相似的问题:
只适应不需要的技术。而不是:
DELETE FROM hostname h
USING unnest(OLD.hostnames) d(x)
WHERE h.hostname = d.x;
...
INSERT INTO hostname(hostname)
SELECT h
FROM unnest(NEW.hostnames) h;
使用:
DELETE FROM prod_sku p
USING jsonb_array_elements(NEW.data->'bags') d(x)
WHERE p.sku = d.x->>'sku';
...
INSERT INTO prod_sku(sku)
SELECT b->>'sku'
FROM jsonb_array_elements(NEW.data->'bags') b
的详细信息: