我想创建一个存储函数,其主体将遍历WITH语句的结果。那可能吗?到目前为止,我在FOR上收到WITH后面的语法错误。最小示例:
DO $$
DECLARE loop_col1 RECORD;
BEGIN
WITH temp_table AS (
SELECT col1, col2 FROM files
)
FOR loop_col1 IN
SELECT DISTINCT col1 FROM temp_table
LOOP
-- do something
raise notice 'loop_uurid %', loop_col1
END LOOP;
END $$;
我想要遍历col1的原因是它对col2的值进行分组,并且对于每组值我都希望在其他表中放置新关系(例如,“做某事”部分)
其他可以让我拥有“临时表”数据的解决方案也很好。
完整的上下文查询:
CREATE OR REPLACE FUNCTION enqueue_postprocessing_jobs()
RETURNS void
LANGUAGE plpgsql AS $$
DECLARE
loop_group_uufid RECORD;
loop_uurid RECORD;
BEGIN
-- 1. Find information of files that might be usable for new postprocessing
-- job. Query results in all files that are related to postprocessing jobs
WITH candidate_postprocessing_files
SELECT uufid, uurid, source, group_uufid
FROM files
WHERE source='CRACKS' OR source='BACKGROUND'
AND uufid NOT IN (
-- Find all files which have do have a job associated with them
SELECT DISTINCT uufid FROM get_files_and_jobs()
WHERE type='POSTPROCESSING'
);
-- 2. Group candidate files by group_uufid (a) and loop over them to see if
-- all necessary files are present (b), insert new job if so (c) and
-- connect job to files (d)
FOR loop_group_uufid IN
SELECT DISTINCT group_uufid
FROM candidate_postprocessing_files
LOOP
-- a. Make reusable temp table with only the files of this group
WITH group_postprocessing_files AS (
SELECT * FROM candidate_postprocessing_files
WHERE group_uufid=loop_group_uufid
),
-- b. Select ids of those files and runs where all necessary files are
-- present. Query results in a table is 0 rows long if not all files
-- are present for this job, otherwise, it should be 2 rows long.
-- One row for cracks, one row for background.
-- In other words, this whole table function as a single job candidate.
job_candidate AS (
SELECT uufid, uurid FROM group_postprocessing_files
WHERE 'CRACKS' IN (SELECT source FROM group_postprocessing_files)
AND 'BACKGROUND' IN (SELECT source FROM group_postprocessing_files)
)
-- c&D. Insert those new jobs and connect files
-- Should only loop once
FOR loop_uurid IN
SELECT DISTINCT uurid FROM job_candidate
LOOP
-- c. Insert jobs
WITH job AS (
-- TODO Support not_before and priority
SELECT enqueue_job AS uujid
FROM enqueue_job(uurid, '' , 'POSTPROCESSING')
)
-- d. Connect new jobs to files
INSERT INTO files_to_jobs
SELECT job_candidate.uufid, job.uujid
FROM job;
END LOOP;
END LOOP;
END $$;
所以我的问题是:
您可以将FOR循环与WITH子句结合使用,但是WITH子句必须属于SELECT语句(WITH子句不是独立的语句:]
DO
$$
DECLARE loop_col1 RECORD;
BEGIN
FOR loop_col1 IN
WITH temp_table AS (
SELECT col1, col2 FROM files
)
SELECT DISTINCT col1 FROM temp_table
LOOP
-- do something
raise notice 'loop_uurid %', loop_col1;
END LOOP;
END $$;
否则,您可以创建一个临时表:
DO $$
DECLARE loop_col1 RECORD;
BEGIN
CREATE TEMPORARY table temp_table ON COMMIT DROP AS
SELECT col1, col2 FROM files;
FOR loop_col1 IN
SELECT DISTINCT col1 FROM temp_table
LOOP
-- do something
raise notice 'loop_uurid %', loop_col1;
END LOOP;
END $$;