2016-02-05 2 views
1

В таблице PostgreSQL 9.5 у меня есть столбец integersocial.Обновление целочисленного столбца из члена jsonb не выполняется: column имеет тип integer, но выражение имеет тип jsonb

Когда я пытаюсь обновить его в хранимой процедуре приведены следующие данные в формате JSON (массив с 2-х объектов, каждый из которых имеет «социальный» ключ) в in_users переменной типа jsonb:

'[{"sid":"12345284239407942","auth":"ddddc1808197a1161bc22dc307accccc",**"social":3**,"given":"Alexander1","family":"Farber","photo":"https:\/\/graph.facebook.com\/1015428423940942\/picture?type=large","place":"Bochum, 
Germany","female":0,"stamp":1450102770}, 
    {"sid":"54321284239407942","auth":"ddddc1808197a1161bc22dc307abbbbb",**"social":4**,"given":"Alxander2","family":"Farber","photo":null,"place":"Bochum, 
Germany","female":0,"stamp":1450102800}]'::jsonb 

Тогда следующий код не удается:

FOR t IN SELECT * FROM JSONB_ARRAY_ELEMENTS(in_users) 
    LOOP 
      UPDATE words_social SET 
        social = t->'social', 
      WHERE sid = t->>'sid'; 
    END LOOP; 

с сообщением об ошибке:

ERROR: column "social" is of type integer but expression is of type jsonb 
LINE 3:       social = t->'social', 
             ^
HINT: You will need to rewrite or cast the expression. 

Я попытался изменить эту строку:

social = t->'social'::int, 

, но затем я получаю ошибку:

ERROR: invalid input syntax for integer: "social" 
LINE 3:       social = t->'social'::int, 
              ^

Почему PostgreSQL не признают, что данные integer?

От JSON-TYPE-MAPPING-TABLE У меня создалось впечатление, что номер JSON будет автоматически преобразован в числовой тип PostgreSQL.

+1

Я отвалил последнего изменения, которые эффективно добавлен новый вопрос. Пожалуйста, задайте новый вопрос, если он еще неясен. –

ответ

1

Один на основе набора команд SQL является гораздо более эффективным, чем зацикливание:

UPDATE words_social w 
SET social = (iu->>'social')::int 
FROM JSONB_ARRAY_ELEMENTS(in_users) iu -- in_user = function variable 
WHERE w.sid = iu->>'sid';    -- type of sid? 

Чтобы ответить на исходный вопрос:

Why doesn't PostgreSQL recognize that the data is integer?

Поскольку вы пытались преобразовать значение jsonb в integer. В вашем решении вы уже нашли, что вам нужен оператор ->> вместо -> для извлечения text, который может быть отлит до integer.

Ваша вторая попытка добавил вторую ошибку:

t->'social'::int

В дополнение к вышесказанному: operator precedence. Оператор литья :: связывается сильнее, чем оператор json ->. Как вы нашли себя уже, вы действительно хотите:

(t->>'social')::int 

Очень похожий случай на dba.SE:

+0

Эрвин, спасибо вам за руководство, но я не уверен, как применить ваше предложение к моему делу - где я петлю через массив jsonb и делаю 'UPDATE' -' ЕСЛИ НЕ НАЙДЕНЫ ТОГДА' - 'INSERT'. См. Мою функцию [words_merge_users()] (https://gist.github.com/afarber/c40b9fc5447335db7d24) для получения дополнительной информации. –

+1

@AlexanderFarber: Возможно, очень элегантное решение с новым 'INSERT ... ON CONFLICT ... DO UPDATE' В Postgres 9.5. Но, пожалуйста, отправьте свой новый вопрос в качестве нового вопроса. –

+0

Erwin, я опубликовал [новый вопрос] (http://stackoverflow.com/questions/35393252/syntax-error-in-upsert-test-code), но, похоже, он не работает с 'ON CONFLICT' для некоторых Данные JSON. –

0

Я закончил с использованием:

FOR t IN SELECT * FROM JSONB_ARRAY_ELEMENTS(in_users) 
LOOP 
     UPDATE words_social SET 
       social = (t->>'social')::int 
     WHERE sid = t->>'sid'; 

     IF NOT FOUND THEN 
       INSERT INTO words_social (social) 
       VALUES ((t->>'social')::int); 
     END IF; 
END LOOP; 
Смежные вопросы