PostgreSQL声明游标cur后执行OPEN cur提示‘cur不存在’的问题
错误原因及修复方案
核心错误点
- DECLARE块位置错误:PL/pgSQL要求所有变量、游标声明必须放在最外层的
DECLARE块中,不能在BEGIN内部嵌套DECLARE声明。你在BEGIN里声明游标cur和变量,导致游标未被正确识别为游标对象,反而被当作未定义的类型,触发ERROR: type "cur" does not exist。 - SELECT语法错误:原查询中
cr.CropId,后面多了一个冗余逗号,会导致语法解析失败。
修正后的代码
DO $$ DECLARE BatchSize INT := 1000; RowCount INT := 0; Done BOOLEAN := FALSE; -- 游标声明移到外层DECLARE cur CURSOR FOR SELECT td.date, so.SoilId, cr.CropId -- 移除冗余逗号,按需添加其他列 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 date_col DATE; SoilId_col INT; CropId_col INT; -- 按需添加其他列对应的变量 BEGIN -- 打开游标 OPEN cur; -- 分批循环处理 LOOP FETCH cur INTO date_col, SoilId_col, CropId_col; -- 按需添加其他变量 -- 无数据则退出循环 IF NOT FOUND THEN Done := TRUE; EXIT; END IF; -- 插入目标表 INSERT INTO YourTargetTable ( date, SoilId, CropId -- 按需添加其他列 ) VALUES ( date_col, SoilId_col, CropId_col -- 按需添加其他值 ); RowCount := RowCount + 1; -- 达到批次大小则退出当前批次 IF RowCount >= BatchSize THEN EXIT; END IF; END LOOP; CLOSE cur; END $$;
更高效的全量分批处理优化
如果需要处理所有数据(而非单批次),可以调整循环逻辑,每次处理一个批次后重置计数器,直到游标耗尽:
DO $$ DECLARE BatchSize INT := 1000; RowCount INT := 0; cur CURSOR FOR SELECT td.date, so.SoilId, cr.CropId 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; date_col DATE; SoilId_col INT; CropId_col INT; BEGIN OPEN cur; LOOP RowCount := 0; -- 批量获取并插入数据 LOOP FETCH cur INTO date_col, SoilId_col, CropId_col; IF NOT FOUND THEN EXIT; END IF; INSERT INTO YourTargetTable (date, SoilId, CropId) VALUES (date_col, SoilId_col, CropId_col); RowCount := RowCount + 1; IF RowCount >= BatchSize THEN EXIT; END IF; END LOOP; -- 无数据则退出外层循环 IF RowCount = 0 THEN EXIT; END IF; -- 可选:批次提交后短暂休眠,避免资源占用过高 -- PERFORM pg_sleep(0.1); END LOOP; CLOSE cur; END $$;
内容的提问来源于stack exchange,提问作者Jetro Olowole
相关产品推荐
相关产品推荐

