I am trying to fetch this query in batches at it contains calculated values before I insert it into another table. So I declare it to fetch in batches.
It seems there might be an issue with cursor naming conventions in my PostgreSQL environment. I tried using it in double quote and it didn’t work too.
When I run the code I got the error message
ERROR: type "cur" does not exist on OPEN cur;
DO $$
DECLARE
BatchSize INT := 1000;
RowCount INT := 0;
Done BOOLEAN := FALSE;
BEGIN
-- Declare a cursor for your SELECT statement
DECLARE cur CURSOR FOR
SELECT
td.date,
so.SoilId,
cr.CropId,
-- Add more more
FROM
Time td
LEFT JOIN
SoilDimension so ON DATE(so.timestamp) = td.date
LEFT JOIN
CropDimension cr ON DATE(cr.timestamp) = td.date
LEFT JOIN
SensorDimension se ON DATE(se.timestamp) = td.date
LEFT JOIN
IrrigationDimension ir ON DATE(ir.timestamp) = td.date
LEFT JOIN
WeatherDimension we ON DATE(we.timestamp) = td.date;
-- Declare variables to hold row values
DECLARE
date_col DATE;
SoilId_col INT;
CropId_col INT;
-- Add more variables for other columns as needed
-- Open the cursor
OPEN cur;
-- Loop to fetch and insert data in batches
LOOP
FETCH cur INTO
date_col,
SoilId_col,
CropId_col;
-- Fetch other column values as needed
-- Check if any rows were fetched, and break the loop if none were fetched
IF NOT FOUND THEN
Done := TRUE;
EXIT;
END IF;
-- Insert the fetched row into YourTargetTable
INSERT INTO YourTargetTable (
date,
SoilId,
CropId,
-- Add other columns here
) VALUES (
date_col,
SoilId_col,
CropId_col,
-- Add other values here
);
-- Increment the row count
RowCount := RowCount + 1;
-- Add a delay if necessary to avoid overwhelming the system
-- PERFORM pg_sleep(1); -- Uncomment this line and adjust the delay as needed
-- Exit the loop if the desired batch size is reached
IF RowCount >= BatchSize THEN
EXIT;
END IF;
END LOOP;
-- Close the cursor
CLOSE cur;
END $$;
2
Answers
You are mixing SQL command
DECLARE
and plpgsql commandOPEN
. It doesn’t work. You should to use only plpgsql syntax. The cursor’s declaration should be beforeBEGIN
.It is little bit messy, because inside PL/pgSQL we can work with SQL commands, and SQL supports cursors, but PL/pgSQL supports cursors little bit different way and uses own implementation. SQL cursors and PL/pgSQL cursors are interface over some API inside Postgres, but these interfaces cannot to cooperate. So inside PL/pgSQL use only PL/pgSQL cursors.
Plpgsql is a block structured language consisting of 3 sections:
With only Execution section required. The Declaration sections contains local variable declarations including cursors. Further blocks are nest-able with
declare
orbegin
starting a new block. Anything declared within an inner block is not visible in an outer block.Your structure contains nested blocks. It can/should(?) be reduced to a single block. So:FYI, this entire block can be reduced to a single SQL statement as:
Issue Your
select ...
statement does not have anorder by
clause which makes the statement nondeterministic. If you run it multiple times you will get different results. This is so for both thedo
block and the single statement.Note: Not tested no test data supplied.