I have a rule that runs on update to a source table. The rule queries data across multiple other tables, formats the data, and inserts it into another transform table. Here is an example of what I have so far.
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
I am trying to pass the NEW value into the subquery, but I receive the error "ERROR: subquery in FROM cannot refer to other relations of same query level". Using NEW in the outermost where statement works, but the query take a long time due to the large amount of data in the tables.
Is it possible to pass the NEW value into the subquery of this rule? I am using PG 8.3 and PGAdmin 1.12
Solved this by implementing a trigger function. As far as I can tell, you cannot pass the NEW value to a subquery in a rule (PG 8.3).
The script below will collect only data from table1 and table2 that corresponds to updated record in old_table, reformat the data, and insert it into new_table. By switching to a trigger and inserting the argument into the base query, the processing time has dropped from ~2 seconds to ~50 ms.
The function:
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;
The trigger:
CREATE TRIGGER
old_table_trigger
BEFORE UPDATE ON
old_table
FOR EACH ROW EXECUTE PROCEDURE get_data();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.