[英]ERROR cursor does not exist after first loop in PL/pgSQL
我需要將大量 csv 文件加載到 PostgreSQL 數據庫中。 我有一個表source_files
,其中包含文件路徑和一個標志,該標志指示是否已經為我需要加載的所有 csv 文件加載了文件。
我編寫了以下代碼,它正確加載了第一個文件,但隨后引發了錯誤:
ERROR: cursor "curs" does not exist
為什么我會收到此錯誤,我該如何解決?
DO $$
DECLARE
file_record record;
curs CURSOR
FOR SELECT id, file_path
FROM source_files
WHERE added_to_db=FALSE
ORDER BY id;
BEGIN
OPEN curs;
LOOP
-- Get next entry in source file which contains name of csv to load
FETCH curs INTO file_record;
exit WHEN NOT found;
BEGIN
-- As we need to add a column to the data after loading csv but before inserting
-- into final table we use a temporary table mytemp
DROP TABLE mytemp;
CREATE TABLE mytemp
(
dataA numeric,
dataB numeric
);
-- Load csv file
EXECUTE FORMAT('COPY mytemp
FROM ''%s''
DELIMITER '',''
CSV HEADER;', file_record.file_path);
-- Add Column specifying what source file the data is from
ALTER TABLE mytemp
ADD COLUMN source_id int;
UPDATE mytemp
SET source_id=file_record.id;
-- Add the data to the destination table
INSERT INTO data_table(
dataA,
dataB,
source_id
)
SELECT
mytemp.dataA,
mytemp.dataB
mytemp.source_id
FROM
mytemp
-- Set a flag to indicate that the current file in source_files has been loaded
UPDATE source_files
SET added_to_db=TRUE WHERE CURRENT OF curs;
COMMIT;
END;
END LOOP;
CLOSE curs;
END $$;
您的代碼有一個大問題是COMMIT
。 您可以在DO
語句中使用COMMIT
,但 cursor 會在事務結束后立即關閉。 在 SQL 中,您可以創建一個 cursor WITH HOLD
,它在事務結束后仍然有效,但在 PL/pgSQL 中不可用。
我建議刪除COMMIT
。
代碼中的另一個錯誤是您使用了 function format
,這會使您面臨 SQL 注入。 代替
FORMAT('COPY mytemp
FROM ''%s''
DELIMITER '',''
CSV HEADER;', file_record.file_path);
利用
FORMAT('COPY mytemp
FROM %L
DELIMITER '',''
CSV HEADER;', file_record.file_path);
您可以通過在循環中使用隱式 cursor 來簡化代碼:
FOR file_record IN
SELECT id, file_path
FROM source_files
WHERE added_to_db=FALSE
ORDER BY id
LOOP
...
END LOOP;
這樣可以節省您聲明 cursor 和EXIT WHEN
的時間。 無論如何, OPEN
和CLOSE
語句都是不必要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.