Ale*_* H. 3 sql postgresql plpgsql cursor window-functions
我看过这个类似的问题,但我认为我的问题可能有所不同.如果我正确理解他们的问题,问题是由上游的语法错误引起的.
在我的情况下,语法错误是如此接近程序的开头,它给了我一个可能出错的窗口,但是一切看起来都没问题.
码:
DO $$
DECLARE topic_cursor CURSOR FOR SELECT * FROM "socialMediaModel_topic" WHERE "active_search"=True;
BEGIN
OPEN topic_cursor;
FETCH FIRST FROM topic_cursor;
LOOP
SELECT "topic" FROM topic_cursor AS "c_topic";
SELECT "topic_id" FROM topic_cursor AS "c_id";
SELECT "active_search" FROM topic_cursor AS "c_active";
INSERT INTO "socialMediaModel_datacollection" ("name", "active")
VALUES (c_topic, c_active);
INSERT INTO "socialMediaModel_datacollectiontopic" ("data_collection_id_id", "topic_id_id")
VALUES ((SELECT "data_collection_id" FROM "DataCollection" where name=c_topic), c_id);
FETCH NEXT FROM topic_cursor;
END LOOP;
CLOSE topic_cursor;
UPDATE "socialMediaModel_topic" SET "active_search" = False WHERE "active_search"=True;
COMMIT;
END$$;
Run Code Online (Sandbox Code Playgroud)
错误:
ERROR: syntax error at or near ";"
LINE 9: FETCH FIRST FROM topic_cursor;
^
********** Error **********
ERROR: syntax error at or near ";"
SQL state: 42601
Character: 247
Run Code Online (Sandbox Code Playgroud)
在编写此脚本时,我几乎完全遵循这些资源:
数据库:PostgreSQL 9.1
编辑器:pgAdmin III查询工具
如果我错过了一些非常明显的事情,我会提前道歉.我一整天都在盯着这个剧本,所以我的大脑可能会有点乱.
您的代码中存在许多问题.
这应该工作,也更快:
DO
$do$
DECLARE
rec record;
BEGIN
FOR rec IN
SELECT s.*, d.data_collection_id
FROM "socialMediaModel_topic" s
LEFT JOIN "DataCollection" d ON d.name = s.topic
WHERE active_search
LOOP
INSERT INTO "socialMediaModel_datacollection" (name, active)
VALUES (rec.topic, rec.active_search);
INSERT INTO "socialMediaModel_datacollectiontopic"
(data_collection_id_id, topic_id_id)
VALUES (rec.data_collection_id, rec.topic_id);
END LOOP;
UPDATE "socialMediaModel_topic"
SET active_search = FALSE
WHERE active_search;
END
$do$;
Run Code Online (Sandbox Code Playgroud)
FETCH语法不正确.
有没有COMMIT在一个DO声明.整个事情在一个事务中自动运行,就像一个函数.
你没有条件终止你的循环.
几乎没有必要使用显式游标.使用更方便(通常更快)的FOR循环隐式游标.
我会建议反对Postgres中的CaMeL案例标识符.仅使用合法的小写标识符.
的整个程序的方法是低劣到与基于集合的方法修改数据的CTE的:
WITH ins1 AS (
INSERT INTO "socialMediaModel_datacollection" (name, active)
SELECT topic, active_search
FROM "socialMediaModel_topic"
WHERE active_search
)
, ins2 AS (
INSERT INTO "socialMediaModel_datacollectiontopic"
(data_collection_id_id, topic_id_id)
SELECT d.data_collection_id, s.topic_id
FROM "socialMediaModel_topic" s
LEFT JOIN "DataCollection" d ON d.name = s.topic
WHERE s.active_search
)
UPDATE "socialMediaModel_topic"
SET active_search = FALSE
WHERE active_search;
Run Code Online (Sandbox Code Playgroud)
或者,如果您有并发写入负载,请使用FOR UPDATE以避免竞争条件:
WITH sel AS (
SELECT s.topic_id, s.topic, s.active_search, d.data_collection_id
FROM "socialMediaModel_topic" s
LEFT JOIN "DataCollection" d ON d.name = s.topic
WHERE s.active_search
FOR UPDATE
)
, ins1 AS (
INSERT INTO "socialMediaModel_datacollection" (name, active)
SELECT topic, active_search FROM sel
)
, ins2 AS (
INSERT INTO "socialMediaModel_datacollectiontopic"
(data_collection_id_id, topic_id_id)
SELECT d.data_collection_id, s.topic_id FROM sel
)
UPDATE "socialMediaModel_topic"
SET active_search = FALSE
WHERE active_search;
Run Code Online (Sandbox Code Playgroud)
有关SELECT ... FOR UPDATECTE的更多信息:
我应该在事务中包含SELECT吗?
类似的问题/答案:
如何在PostgreSQL中使用游标提高函数的性能?