2014-03-20 3 views
1

У меня есть правило, которое выполняется при обновлении в исходную таблицу. Правило запрашивает данные в нескольких других таблицах, форматирует данные и вставляет их в другую таблицу преобразования. Вот пример того, что у меня до сих пор.Правило PG - использование NEW в подзапросе

CREATE OR REPLACE RULE 
    value_insert 

AS ON UPDATE TO 
    source_table 

DO ALSO INSERT INTO transform_table(
    username 
    ,status 
    ,section 
) 
SELECT 
    username 
    ,MAX(status) 
    ,MAX(section) 
FROM 
(
SELECT 
    username 
    ,CASE 
    WHEN item = status 
    THEN value 
    ELSE NULL 
    END AS status 
    ,CASE 
    WHEN item = section 
    THEN value 
    ELSE NULL 
    END AS section 
FROM 
(
SELECT 
    username 
    ,item 
    ,value 
FROM 
    table1 
    ,table2 
WHERE 
    item = status 
    OR item = section 
    AND source_table.username = NEW.username 
) 
) 
GROUP BY 
    username 

Я пытаюсь передать новое значение в подзапрос, но я получаю ошибку «ERROR: подзапрос в FROM не может ссылаться на другие отношения того же уровня запросов». Использование NEW в самом внешнем, где работает оператор, но запрос занимает много времени из-за большого объема данных в таблицах.

Возможно ли передать новое значение в подзапрос этого правила? Я использую PG 8.3 и PGAdmin 1.12

ответ

0

Решил это, реализовав функцию триггера. Насколько я могу судить, вы не можете передать значение NEW в подзапрос в правиле (PG 8.3).

В приведенном ниже скрипте будут собираться только данные из таблицы1 и таблицы2, которые соответствуют обновленной записи в old_table, переформатировать данные и вставить их в new_table. Переключившись на триггер и вставив аргумент в базовый запрос, время обработки снизилось с ~ 2 секунд до ~ 50 мс.

Функция:

CREATE OR REPLACE FUNCTION get_data() 
RETURNS TRIGGER AS $$ 

BEGIN 

INSERT INTO new_table(
    username 
    ,status 
    ,section 
) 
SELECT 
    username 
    ,MAX(status) 
    ,MAX(section) 
FROM 
(
SELECT 
    username 
    ,CASE 
    WHEN item = status 
    THEN value 
    ELSE NULL 
    END AS status 
    ,CASE 
    WHEN item = section 
    THEN value 
    ELSE NULL 
    END AS section 
FROM 
(
SELECT 
    username 
    ,item 
    ,value 
FROM 
    table1 
    ,table2 
WHERE 
    (item = status OR item = section) 
    AND table1.username = table2.username 
    AND table2.username = old_table.username 
    AND old_table.username = NEW.username 
) 
) 
GROUP BY 
    username; 

RETURN NEW; 

END; 

$$ 

LANGUAGE plpgSQL; 

Триггер:

CREATE TRIGGER 
    old_table_trigger 

BEFORE UPDATE ON 
    old_table 

FOR EACH ROW EXECUTE PROCEDURE get_data(); 
Смежные вопросы