Используйте wCTE, чтобы ОБНОВИТЬ только что вставленное значение

У меня есть 2 таблицы - пользователи, документы. Используя RETURN, я возвращаю user_id (вновь созданный при вставке) и doc_id (вновь созданный при вставке).

Мне нужно обновить столбец в таблице, документы на основе возвращаемых значений при вставке.

Скажем, в таблице пользователей есть

user_id| user_name| user_address
1      | user1    | 1addressline1
2      | user2    | 2addressline1

таблица документов имеет

doc_id| doc_name| reference_id | user_id
1     | 1doc    |              | 1
2     | 2doc    |              | 2

Мне нужно обновить столбец reference_id значением, аналогичным doc_id (возвращается при вставке)

Doc_id и user_id создаются автоматически.

With row1 as (
    insert into users(user_name,user_address) 
    values('user3','useraddress3')
   RETURNING user_id
),row2 as (
   insert into documents(doc_name,user_id) 
   SELECT '"+3doc+"',user_id from row1 RETURNING doc_id
) 
UPDATE documents 
  set reference_id=doc_id 
where user_id=user_id 
SELECT user_id,doc_id from row1,row2;

Скажем, 3doc - это строковая переменная, содержащая имя документа.

Я не могу выполнить обновление в том же запросе.

С уважением, Нихил


person nikhil    schedule 07.01.2015    source источник
comment
SELECT '"+3doc+"' неверный SQL. Конкатенация строк выполняется с использованием || в SQL. Плюс у вас есть два утверждения после CTE. У вас может быть только один оператор (выбор) в качестве последнего оператора в CTE.   -  person a_horse_with_no_name    schedule 07.01.2015
comment
@a_horse_with_no_name Весь этот запрос входит в мой Java-код и, следовательно, в '+ 3doc +' .. Предположим, что в качестве аргумента я не вставляю это значение (только user_id в таблице документов)   -  person nikhil    schedule 07.01.2015
comment
Позвольте мне переформулировать свой вопрос С row1 как (вставить в users (user_name, user_address) values ​​('user3', 'useraddress3') RETURNING user_id), row2 as (insert into documents (user_id) SELECT user_id from row1 RETURNING doc_id) UPDATE документы устанавливают reference_id = doc_id, где user_id = user_id SELECT user_id, doc_id из row1, row2;   -  person nikhil    schedule 07.01.2015
comment
Есть ли <я> не использование конкатенации для вставки возможно пользователем значения в запросах SQL. См bobby-tables.com, en.wikipedia.org/wiki/SQL_injection, docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html   -  person Craig Ringer    schedule 07.01.2015
comment
@CraigRinger Спасибо за того, что ссылки. Но я до сих пор не удалось обновить недавно вставленную строку на основе двух возвращаемые значения и обновления столбца (REFERENCE_ID) с тем же значением, как он появляется на колонке 1 (doc_id)   -  person nikhil    schedule 07.01.2015
comment
Что намеченная цель этого UPDATE? Как написано выше, ваш запрос не имеет смысла, у вас есть UPDATE ... SELECT ... там, который является поддельным синтаксис.   -  person Craig Ringer    schedule 07.01.2015


Ответы (1)


WCTE не может обновить только что вставленную строку. Один термин CTE не «видит» изменения, внесенные другим термином CTE.

Цитата из руководства:

Подоператоры в WITH выполняются одновременно друг с другом и с основным запросом. Следовательно, при использовании операторов изменения данных в WITH порядок, в котором на самом деле происходят указанные обновления, непредсказуем. Все операторы выполняются с одним и тем же снимком (см. Главу 13), поэтому они не могут «видеть» влияние друг друга на целевые таблицы.

и

Попытка обновить одну и ту же строку дважды в одном операторе не поддерживается.

Другими словами, вы не можете сделать то, что пытаетесь сделать, в одном запросе, по крайней мере, так, как вы пытаетесь это сделать.

Если вы хотите, чтобы для reference_id было установлено то же значение, что и для doc_id при вставке строки, используйте триггер BEFORE INSERT FOR EACH ROW, который проверяет, является ли reference_id NULL, и, если это так, устанавливает NEW.reference_id := NEW.doc_id.

person Craig Ringer    schedule 07.01.2015
comment
Спасибо за это. Так как я могу сохранить возвращаемые значения? - person nikhil; 07.01.2015
comment
@nikhil См редактирования. Трудно быть уверенным, потому что это не совсем понятно, почему вы пытаетесь сделать то, что вы, кажется, пытаются - то, что основная цель состоит в том, реальная проблема, которую вы пытаетесь решить. - person Craig Ringer; 07.01.2015
comment
Если бы вы могли вести меня в сохранении возвращаемых значений 2 переменных, это будет решить мою проблему. - person nikhil; 07.01.2015
comment
@nikhil PostgreSQL не имеет переменные. Так что я не могу. Если вы просто хотите, чтобы получить их в виде кортежа из запроса WITH, простой SELECT 'u', user_id FROM row1 UNION ALL 'd', doc_id FROM row2 будет достаточно. Или SELECT user_id, doc_id FROM row1 CROSS JOIN row2, если вы предпочитаете их в одном ряду. Это все еще не ясно, <я> почему вы пытаетесь использовать wCTE для этого, а не просто стреляя несколько отдельных запросов. Похоже, вы усложнять проблему. - person Craig Ringer; 07.01.2015
comment
Спасибо за это. Я думаю, что разделит мои запросы. Это будет проще. - person nikhil; 07.01.2015
comment
@nikhil Да, или написать простой PL / PgSQL хранимой процедуры, с помощью которых это довольно легко. - person Craig Ringer; 07.01.2015