2016-03-24 2 views
0

Вот упрощенная версия запроса, который я пытаюсь написать. Он предназначен для сохранения строки как переменной combine, затем UPDATE в таблице media_hashtags, если существует определенная запись, иначе INSERT эту запись.Postgres Вставка/обновление запроса не работает должным образом

WITH 
     combine AS (
     SELECT * FROM hashtags WHERE hashtag_text='HOPPA' 
    ) 
    UPDATE media_hashtags SET hashtag_id = (SELECT id FROM combine) WHERE user_id = 58 AND media_id=161; 
     INSERT INTO media_hashtags (media_id, user_id, hashtag_id) 
    SELECT 161, 58, (SELECT id FROM combine) 
    WHERE NOT EXISTS (
     SELECT * FROM media_hashtags 
     WHERE (
     user_id = 58 AND 
     media_id = 161 
    ) 
    ) 

    RETURNING * 

Однако, я получаю эту ошибку:

ERROR: relation "combine" does not exist 
LINE 8:  SELECT 161, 58, (SELECT id FROM combine) 

Интересно, что если я сделать запрос с только UPDATE или только INSERT команды, то она выполняется, как ожидалось. Ошибка возникает только тогда, когда я делаю это сразу. Любые идеи о том, что проблема, и исправление?

+2

Там, кажется, две отдельных запросы (поиск точки с запятой). Естественно, что второй не видит «комбайн» с первого – leonbloy

+0

. Это имеет смысл. Полагаю, я мог бы переписать комбайн, но это было бы многословием. Есть ли лучший способ решить эту проблему? – dmwong2268

ответ

1

У вас есть два запроса, первый заканчивается ; после UPDATE заявления. Следующий INSERT больше не видит CTE, потому что это новое утверждение.

Если вы хотите запустить это как одно утверждение, что вам нужно, чтобы переместить UPDATE в собственный КТР:

WITH combine AS (
    SELECT id 
    FROM hashtags 
    WHERE hashtag_text='HOPPA' 
), changed AS (
    UPDATE media_hashtags 
    SET hashtag_id = (SELECT id FROM combine) 
    WHERE user_id = 58 
    AND media_id=161 
) 
INSERT INTO media_hashtags (media_id, user_id, hashtag_id) 
SELECT 161, 58, (SELECT id FROM combine) 
WHERE NOT EXISTS (
    SELECT * FROM media_hashtags 
    WHERE (
    user_id = 58 AND 
    media_id = 161 
) 
) 
RETURNING *; 

Вы также должны выбрать только столбцы, необходимые в начальной КТР. Тот факт, что последующие операторы используют только один столбец от combine, не будет перенесен в первый запрос, поэтому Postgres может не запрашивать hashtags настолько эффективно, насколько это возможно.


Если вы используете Postgres 9.5 вы можете упростить формулировку, используя пункт on conflict для insert заявления:

INSERT INTO media_hashtags (media_id, user_id, hashtag_id) 
SELECT 161, 58, id 
FROM hashtags 
WHERE hashtag_text='HOPPA' 
ON CONFLICT (media_id, user_id) DO UPDATE 
    SET hashtag_id = excluded.hashtag_id; 

Это требует уникального индекса media_hashtags(media_id, user_id)

1

Вы можете использовать временную таблицу для хранения данных из хэштегов, а затем вставлять и обновлять операции.

Вот так:

DROP TABLE IF EXISTS temp_hashtags; 
CREATE TEMP TABLE temp_hashtags AS 
SELECT * FROM hashtags WHERE hashtag_text='HOPPA'; 

UPDATE media_hashtags 
    SET hashtag_id = (SELECT id FROM temp_hashtags) 
WHERE user_id = 58 AND media_id=161; 

INSERT INTO media_hashtags (media_id, user_id, hashtag_id) 
SELECT 161, 58, (SELECT id FROM temp_hashtags) 
WHERE NOT EXISTS (
     SELECT * FROM media_hashtags 
     WHERE user_id = 58 AND media_id = 161 
     ); 
Смежные вопросы