Обновите JSONB с помощью psycopg2

#python #postgresql #psycopg2 #jsonb

#python #postgresql #psycopg2 #jsonb

Вопрос:

Следующий оператор SQL для базы данных PostgreSQL с несколькими схемами (v.12) является абсолютно корректным и достигает желаемого результата.

Мне нужно обновить глубокое значение JSONB, как показано ниже:

 UPDATE schema."Some_table_name" SET jsonb_col = jsonb_set(jsonb_col, '{path,to,key}', '"string value"') WHERE id = 1;
  

Когда я пытаюсь выполнить вышеуказанное с помощью python psycopg2 , я не получаю никаких ошибок, но и обновлений тоже нет.

 def update_method(schema, path, value):
   q = f"""UPDATE {schema}."Some_table_name" SET jsonb_col = jsonb_set(jsonb_col, '{path}', '{value}') WHERE id = 1"""
   cur = conn.cursor()
   cur.execute(q)
   conn.commit()
   cur.close()

update_method('schema_name', '{path,to,key}', '"string value"') 
  

Я попытался специально указать путь внутри моего q оператора, как: '{path}'::text[] . По-прежнему нет ни ошибки, ни обновления.

Есть идеи, как я могу обновить глубокий JSONB, используя psycopg2 и метод, подобный приведенному выше?

РЕДАКТИРОВАТЬ — прочитав комментарии и попробовав код @Abelisto, я понял, что будет работать (и я чувствую себя немного глупо). Следующий код корректно обновляет любое глубокое значение JSONB:

 def update_method(connection, schema, path, value):
   q = f"""UPDATE {schema}."Some_table_name" SET jsonb_col = jsonb_set(jsonb_col, '{path}', '{value}') WHERE id = 1"""
   cur = connection.cursor()
   cur.execute(q)
   connection.commit()
   cur.close()

update_method(conn, 'schema_name', '{path,to,key}', '"string value"') 
  

Комментарии:

1. Вы действительно пропустили jsonb_set в коде python или это просто опечатка?

2. @Abelisto, просто опечатка.

3. Работает для меня (хотя, вероятно, он подвержен атакам SQL-инъекций). Возможно, указанный путь на самом деле не существует в указанной строке, поэтому обновление не вносит никаких видимых изменений.

4. Для меня остается загадкой, почему глобальная переменная не работает, но используя ее в качестве параметра функции, она работает. Пожалуйста, опубликуйте ответ о первом и втором фрагментах кода и почему первый сбой, а второй успешный.

Ответ №1:

На самом деле это не решение, но сложно опубликовать код python в комментариях.

Этот вопрос определенно нуждается в некоторой отладке. IMO этого фрагмента кода должно быть достаточно, чтобы найти источник проблемы:

 #!/usr/bin/python3

import psycopg2

schema_name = 'pg_temp'
table_name = 'foo'
init_value = '{"a": "x", "b": {"c": "y"}}'

conn = psycopg2.connect('')

c = conn.cursor();
c.execute(f"""create table {schema_name}.{table_name}(id int, col jsonb)""")
c.execute(f"""insert into {schema_name}.{table_name} values(1, '{init_value}')""")
c.execute(f"""select * from {schema_name}.{table_name} where id = 1""")
print(c.fetchall())

def update_method(schema, path, value):
    qs = f"""select * from {schema}.{table_name} where id = 1"""
    q = f"""UPDATE {schema}.{table_name} SET col = jsonb_set(col, '{path}', '{value}') WHERE id = 1"""
    cur = conn.cursor()
    cur.execute(qs)
    print(cur.fetchall())
    print(q)
    cur.execute(q)
    cur.execute(qs)
    print(cur.fetchall())
    conn.commit()
    cur.close()

update_method(schema_name, '{b,c}', '"string value"') 
  

Вывод:

 [(1, {'a': 'x', 'b': {'c': 'y'}})]
[(1, {'a': 'x', 'b': {'c': 'y'}})]
UPDATE pg_temp.foo SET col = jsonb_set(col, '{b,c}', '"string value"') WHERE id = 1
[(1, {'a': 'x', 'b': {'c': 'string value'}})]
  

Как вы можете видеть, код работает для этого простого тестового примера.