查看Postgres 9.4数据类型JSONB的文档,对我来说如何对JSONB列进行更新并不是很明显.
JSONB类型和函数的文档:
http://www.postgresql.org/docs/9.4/static/functions-json.html http://www.postgresql.org/docs/9.4/static/datatype-json.html
作为示例,我有这个基本的表结构:
CREATE TABLE test(id serial, data jsonb);
Run Code Online (Sandbox Code Playgroud)
插入很简单,如:
INSERT INTO test(data) values ('{"name": "my-name", "tags": ["tag1", "tag2"]}');
Run Code Online (Sandbox Code Playgroud)
现在,我将如何更新"数据"列?这是无效的语法:
UPDATE test SET data->'name' = 'my-other-name' WHERE id = 1;
Run Code Online (Sandbox Code Playgroud)
这个文件记录在哪里,我错过了吗?谢谢.
我需要从json类型列中删除一些属性.
桌子:
CREATE TABLE my_table( id VARCHAR(80), data json);
INSERT INTO my_table (id, data) VALUES (
'A',
'{"attrA":1,"attrB":true,"attrC":["a", "b", "c"]}'
);
Run Code Online (Sandbox Code Playgroud)
现在,我需要attrB从列中删除data.
像alter table my_table drop column data->'attrB';这样的东西会很好.但是使用临时表的方法也足够了.
鉴于此类型:
-- Just for testing purposes:
CREATE TYPE testType as (name text)
Run Code Online (Sandbox Code Playgroud)
我可以使用此函数动态获取字段的值:
CREATE OR REPLACE FUNCTION get_field(object anyelement, field text) RETURNS text as
$BODY$
DECLARE
value text;
BEGIN
EXECUTE 'SELECT $1."' || field || '"'
USING object
INTO value;
return value;
END;
$BODY$
LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)
呼叫get_field('(david)'::testType, 'name')按预期工作返回"大卫".
但是如何在复合类型中设置字段的值?我试过这些功能:
CREATE OR REPLACE FUNCTION set_field_try1(object anyelement, field text, value text)
RETURNS anyelement
as
$BODY$
DECLARE
value text;
BEGIN
EXECUTE '$1."' || field || '" := $2'
USING object, value; …Run Code Online (Sandbox Code Playgroud) 通过json字段查询Postgres 9.3非常棒.但是我找不到更新json对象的正式方法,为此我使用plpythonu编写的内部函数基于之前的帖子(如何修改新的PostgreSQL JSON数据类型中的字段?):
CREATE OR REPLACE FUNCTION json_update(data json, key text, value json)
RETURNS json AS
$BODY$
from json import loads, dumps
if key is None: return data
js = loads(data)
js[key] = value
return dumps(js)
$BODY$
LANGUAGE plpythonu VOLATILE
Run Code Online (Sandbox Code Playgroud)
当我的json更新保持扁平和简单时,它的效果非常好.假设"聊天"是在"GO_SESSION"表中提交的json类型,并包含{"a":"1","b":"2"},以下代码将更改"b"值并将"chat"更改为是{"a":"1","b":"5"}
update "GO_SESSION" set chat=json_update(chat,'b','5') where id=3
Run Code Online (Sandbox Code Playgroud)
问题是当我试图给'b'另一个对象而不是一个简单的值时:
update "GO_SESSION" set chat=json_update(chat,'b','{"name":"steve"}') where id=3
Run Code Online (Sandbox Code Playgroud)
数据库中的结果是'b'包含转义字符串而不是真正的json对象:
{"a":"1","b":"{\"name \":\"steve \"}"}
我已经尝试了不同的方法来unescape或转储我的json以保持'b'为对象,但找不到解决方案.
谢谢
更新关系表时:
CREATE TABLE foo ( id serial primary key, credit numeric);
UPDATE foo SET bar = bar + $1 WHERE id = $2;
Run Code Online (Sandbox Code Playgroud)
但是,JSON中的等效项不起作用:
CREATE TABLE foo ( id serial primary key, data json);
UPDATE foo SET data->'bar' = data->'bar' + $1 WHERE id = $2;
Run Code Online (Sandbox Code Playgroud)
我得到的错误是error: syntax error at or near "->"- 这是相当模糊的.
我该怎么做呢?
我正在使用postgres 9.3.4
根据@ GordonLinoff在下面的评论,我创建了一个功能请求:https://postgresql.uservoice.com/forums/21853-general/suggestions/6466818-create-update-delete-on-json-keys
如果您也想要此功能,可以对其进行投票.
我有一个表,其中一列声明为 json,我需要通过向 json 值添加键值来更新记录。
模型
class User(db.Model):
__tablename__ = 'users'
loginId = db.Column(db.String(128), nullable=False, primary_key=True)
_password = db.Column(db.String(128), nullable=True)
views = db.Column(JSON, nullable=True)
Run Code Online (Sandbox Code Playgroud)
控制器
@mod_event.route('/view', methods=['POST'])
def view():
try:
params = request.json
loginId = params['dream']['loginId']
users.update().\
where(users.c.loginId==loginId).\
values(views=<query>))
Run Code Online (Sandbox Code Playgroud)
假设当前值为views{'1001' : 1} 如果必须将查询views更新为 -
如果我不想先查询该值,请更改并更新回来。
我很难在一个查询中弄清楚如何做到这一点,请帮忙,谢谢!
如何修改PostgreSQL JSONB数据类型中的单个字段?
假设我有一张叫做动物的桌子:
id info
------------------------------------------------------------
49493 {"habit1":"fly","habit2":"dive","location":"SONOMA NARITE"}
Run Code Online (Sandbox Code Playgroud)
我想简单地更改location属性的值(例如,大写或小写文本).所以结果,在UPDATE之后
id info
------------------------------------------------------------
49493 {"habit1":"fly","habit2":"dive","location":"sonoma narite"}
Run Code Online (Sandbox Code Playgroud)
我在下面尝试了这个,它不起作用
update animal set info=jsonb_set(info, '{location}', LOWER(info->>'location'), true) where id='49493';
----------------------------------
ERROR: function jsonb_set(jsonb, unknown, text, boolean) does not exist
LINE 7: update animal set info=jsonb_set(info, '{con...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********
ERROR: function jsonb_set(jsonb, unknown, text, boolean) does not exist
Run Code Online (Sandbox Code Playgroud)
如果我只是知道更新的值是什么,那么我可以使用这个:
update animal set info=jsonb_set(info, '{location}', …Run Code Online (Sandbox Code Playgroud) 所以我想试试jsonbPostgreSQL.在我的表,我有一个名为列extras的jsonb类型.
示例数据extras看起来像{"param1": 10, "param2": 15}
我想仅使用sql语句修改JSON.我想做这样的事情:
更新param1的extras通过,如果添加10到其值字段param2的extras超过12.
我该如何编写这样的SQL语句?我知道我可以很容易地在应用程序层中执行此操作,但我想在SQL层本身中执行此操作,因为我可能会处理的行数会很大而且我不想在db-application中浪费时间 - db往返
考虑以下:
create table tmp.x (i integer, t text);
create table tmp.y (i integer, t text);
delete from tmp.x;
delete from tmp.y;
insert into tmp.x values (1, 'hi');
insert into tmp.y values(1, 'there');
insert into tmp.y values(1, 'wow');
Run Code Online (Sandbox Code Playgroud)
在上面, table 中有一行x我想更新。在 table 中y,有两行,我都想将这两行“馈送到”更新中。
以下是我的尝试:
update tmp.x
set t = x.t || y.t
from ( select * from tmp.y order by t desc ) y
where y.i = x.i;
select * from tmp.x;
Run Code Online (Sandbox Code Playgroud)
x.t我希望的值为 ,'hiwowthere'但最终的值为 …
我目前对在django rest-framework中使用JSONField很熟悉,但是我找不到更新存储json中密钥的任何直接方法。过滤JSONField的方法有很多,取决于它的内部键,但是似乎没有办法从已存储的JSONField中更改,更新或删除键。但是似乎postgres可以对json键做一些修改,如这个答案所解释。
是否有任何功能可以对JSONFields进行修改。如果没有任何直接命令可以执行此操作,那么实现JSONField修改的最佳方法是什么?
编辑:
例如,如果我有一个这样的模型:
class Thing(models.Model):
name = models.CharField()
properties = JSONField()
Run Code Online (Sandbox Code Playgroud)
在properties我存储这样的json:
{
"color" : "red",
"size" : "large",
"cost" : 1234
}
Run Code Online (Sandbox Code Playgroud)
然后,我想使用django命令将颜色更改为“绿色”。
我正在使用9.6版本.我的文档看起来像这样:
{
"name" : "John Doe",
"phones" : [
{
"type" : "mobile",
"number" : "555-555-0000",
"deleted": false
},
{
"type" : "home",
"number" : "555-555-0001",
"needsUpdated" : true
},
{
"type" : "work",
"number" : "555-555-0002"
}
]
}
Run Code Online (Sandbox Code Playgroud)
我创建了这样的:
create table t_json (c_json json not null);
insert into t_json (c_json) values ('{"name":"John Doe","phones": [{"type":"mobile","number":"555-555-0000"},{"type":"home","number":"555-555-0001"},{"type": "work","number": "555-555-0002"}]}');
insert into t_json (c_json) values ('{"name":"Jane Dane","phones": [{"type":"mobile","number":"555-555-0030"},{"type":"home","number":"555-555-0020"},{"type": "work","number": "555-555-0010"}]}');
Run Code Online (Sandbox Code Playgroud)
现在我想弄清楚如何A,选择名为John Doe的行,并将他的手机号码更新为"555-555-0003".
从这里Postgresql 9.6文档我发现我可以查询正确的文档,如下所示:
select c_json …Run Code Online (Sandbox Code Playgroud) 我已经在 StackOverflow 上看到了一些对此问题的其他回答,但没有一个对我有用。
{
"data": {
"list": [
{"id": "2ac5bf6f-bc4a-49e8-8f9f-bc518a839981", "type": "type1"},
{"id": "d15ac090-11ce-4c0c-a05d-d4238f01e8b0", "type": "type3"},
{"id": "b98958fa-87c4-4dcc-aa84-beaf2b32c5c0", "type": "type1"},
{"id": "854f4d2a-f37c-42cb-9a1f-17a15454a314", "type": "type2"},
{"id": "555816da-4547-4a82-9e7e-1e92515bd82b", "type": "type2"},
{"id": "0f7f4ced-61c2-45da-b15c-0e12058f66a7", "type": "type4"}
]
}
}
Run Code Online (Sandbox Code Playgroud)
这个 Json 存储在一个名为“questions”的字段中,现在我想在该表中查询列表中具有特定 id 的对象。所以说我有 id 555816da-4547-4a82-9e7e-1e92515bd82b,我想返回
{"id": "555816da-4547-4a82-9e7e-1e92515bd82b", "type": "type2"}
Run Code Online (Sandbox Code Playgroud)
我在互联网上看到的解决方案(主要是在这里),但没有起作用,如下:
SELECT questions->'data'->'list'
FROM assignments
WHERE id='81asd6230-126d-4bc8-9745-c4333338115c'
AND questions->'data'->'list' @> '[{"id":"854f4d2a-f37c-42cb-9a1f-17a15454a314"}]';
Run Code Online (Sandbox Code Playgroud)
我已经在多个不同的响应中看到了这个解决方案,但它根本没有缩小数组范围,它每次都返回完整的内容。where 子句中的第一个 id 是我想要的特定赋值对象的 id,它在这里基本上不相关。
SELECT questions->'data'->'list'
FROM assignments
WHERE id='81asd6230-126d-4bc8-9745-c4333338115c'
AND questions->'data'->'list' @> '[{"id":"854f4d2a-f37c-42cb-9a1f-17a15454a314"}]';
Run Code Online (Sandbox Code Playgroud)
这不会返回任何内容。
有谁知道如何轻松地做到这一点?
我一直在尝试更新以下内容:
{"boxes": {"book": 2, "moving": 2}, "goods": {}}
Run Code Online (Sandbox Code Playgroud)
到 :
{"boxes": {"book_new": 2, "moving": 2}, "goods": {}}
Run Code Online (Sandbox Code Playgroud)
不使用正则表达式或在 ruby 中执行此操作。但似乎有点棘手。我想添加新密钥然后删除旧密钥,我不熟悉语法,而且我在互联网上找不到太多东西。
我能够向数据添加新元素,但不能向嵌套框添加新元素!!像那样:
Update moves SET data = data::jsonb || '{"bookasas": 2}' WHERE data ->> 'boxes' LIKE '%book%';
Run Code Online (Sandbox Code Playgroud)
任何帮助表示赞赏。
postgresql ×13
json ×8
jsonb ×5
sql ×5
sql-update ×3
python ×2
arrays ×1
composite ×1
crud ×1
django ×1
plpgsql ×1
sqlalchemy ×1
types ×1