PostgreSQL 中的游标循环
cursor loop in PostgreSQL
以下代码是 PostgreSQL 9.0 中的游标。我想通过加入多个 table 来获取我的记录,并且我正在从该加入中获取 JSON 数据。
所以我想循环这些记录并使用类似
的查询来解析 json
SELECT "Dump"->'activities-steps'->0->'value' as "steps"
FROM "ActivitySessionDump" where "Id"=42594321345021288
然后我必须从这个查询中获取数据并插入到其他table如
insert to table name (key,value);
所以我准备了一个只读游标来完成这个任务
begin work;
DECLARE
sessionids INSENSITIVE no scroll CURSOR FOR
SELECT asn."Id",asn."UserId",asn."ActivityId",ad."Dump"
FROM "ActivitySession" as asn inner join "ActivitySessionDump" as ad
on asn."Id"=ad."ActivitySessionId"
where asn."CreatedAt" between now() - interval '5 hours' and now() and asn."ActivityId"=1
for read only;
---- i want her loop should start and i will parse a json Dump by executing query--------
--------insert record to another table---------------
---end loop-----------
FETCH next FROM sessionids;
CLOSE sessionids;
COMMIT WORK;
真的有帮助appreciated.Thanks
由于无法在 SQL 中循环,因此您必须使用 PL/pgSQL,例如使用 DO
语句。
在您的情况下,可能如下所示:
DO
$$DECLARE
asn_id ...;
asn_userid ...;
...
c refcursor;
BEGIN
/* assign the SQL cursor to the refcursor variable */
c := 'sessionids';
LOOP
FETCH c INTO asn_id, asn_userid, ...;
IF NOT FOUND THEN EXIT; END IF;
/* process the result row */
END LOOP;
END;$$;
当然在SQL中声明游标,在PL/pgSQL中使用就有点别扭了。
将语句放在 FOR
循环中可能会更好:
FOR asn_id, asn_userid, ... IN
SELECT ...
LOOP
/* process the result row */
END LOOP;
也许您甚至可以将整个事情压缩到一个 INSERT
语句中,这样效率最高:
INSERT INTO ...
(SELECT ...);
这是我的问题的代码,我无法
EXECUTE 'SELECT rec."Dump"::json#>''{activities-steps,0}''->>''value'' 作为步骤' INTO jsonrec;线;
SELECT '{"activities-steps":[{"dateTime":"2016-10-17","value":"4023"}]}'::json#>'{activities-steps,0}'->>'value'作为步数;
我在哪里可以在控制台中执行此代码。
但内部函数我不能。
CREATE OR REPLACE FUNCTION ThirdPartyDataParse()
RETURNS text AS $$
DECLARE
sessionid NO SCROLL CURSOR FOR SELECT asn."Id",asn."UserId",asn."ActivityId",pd."DataSourceId",ad."Dump"::TEXT
FROM "Development"."ActivitySession" as asn inner join "Development"."PersonDataSource" as pd on pd."UserId" = asn."UserId" inner join "Development"."ActivitySessionDump" as ad
on asn."Id"=ad."ActivitySessionId" where asn."CreatedAt" between now() - interval '5 days' and now() and asn."ActivityId"=1 and pd."DataSourceId"=1 for read only;
titles TEXT DEFAULT '';
rec record;
jsonrec record;
BEGIN
OPEN sessionid;
loop
FETCH sessionid INTO rec;
--raise notice '%d',rec."UserId";
if not found then
exit ;
end if;
EXECUTE 'SELECT rec."Dump"::json#>''{activities-steps,0}''->>''value'' as steps ' INTO jsonrec;
titles := titles || ',' || jsonrec."steps";
end loop;
return titles;
END;
$$ LANGUAGE plpgsql;
据我所知,循环或函数是不必要的。它可以替换为使用字符串聚合的简单查询:
SELECT string_agg("Dump"->'activities-steps'->0->'value', ',') as steps
FROM "ActivitySessionDump" d
WHERE d."ActivitySessionId" IN (SELECT asn."Id"
FROM "ActivitySession" as asn
join "PersonDataSource" as pd on pd."UserId" = asn."UserId"
where asn."CreatedAt" between now() - interval '5 days' and now()
and asn."ActivityId" = 1
and pd."DataSourceId" = 1);
无关,但是:你应该真的避免那些可怕的引用标识符
以下代码是 PostgreSQL 9.0 中的游标。我想通过加入多个 table 来获取我的记录,并且我正在从该加入中获取 JSON 数据。
所以我想循环这些记录并使用类似
的查询来解析 jsonSELECT "Dump"->'activities-steps'->0->'value' as "steps"
FROM "ActivitySessionDump" where "Id"=42594321345021288
然后我必须从这个查询中获取数据并插入到其他table如
insert to table name (key,value);
所以我准备了一个只读游标来完成这个任务
begin work;
DECLARE
sessionids INSENSITIVE no scroll CURSOR FOR
SELECT asn."Id",asn."UserId",asn."ActivityId",ad."Dump"
FROM "ActivitySession" as asn inner join "ActivitySessionDump" as ad
on asn."Id"=ad."ActivitySessionId"
where asn."CreatedAt" between now() - interval '5 hours' and now() and asn."ActivityId"=1
for read only;
---- i want her loop should start and i will parse a json Dump by executing query--------
--------insert record to another table---------------
---end loop-----------
FETCH next FROM sessionids;
CLOSE sessionids;
COMMIT WORK;
真的有帮助appreciated.Thanks
由于无法在 SQL 中循环,因此您必须使用 PL/pgSQL,例如使用 DO
语句。
在您的情况下,可能如下所示:
DO
$$DECLARE
asn_id ...;
asn_userid ...;
...
c refcursor;
BEGIN
/* assign the SQL cursor to the refcursor variable */
c := 'sessionids';
LOOP
FETCH c INTO asn_id, asn_userid, ...;
IF NOT FOUND THEN EXIT; END IF;
/* process the result row */
END LOOP;
END;$$;
当然在SQL中声明游标,在PL/pgSQL中使用就有点别扭了。
将语句放在 FOR
循环中可能会更好:
FOR asn_id, asn_userid, ... IN
SELECT ...
LOOP
/* process the result row */
END LOOP;
也许您甚至可以将整个事情压缩到一个 INSERT
语句中,这样效率最高:
INSERT INTO ...
(SELECT ...);
这是我的问题的代码,我无法 EXECUTE 'SELECT rec."Dump"::json#>''{activities-steps,0}''->>''value'' 作为步骤' INTO jsonrec;线;
SELECT '{"activities-steps":[{"dateTime":"2016-10-17","value":"4023"}]}'::json#>'{activities-steps,0}'->>'value'作为步数; 我在哪里可以在控制台中执行此代码。
但内部函数我不能。
CREATE OR REPLACE FUNCTION ThirdPartyDataParse()
RETURNS text AS $$
DECLARE
sessionid NO SCROLL CURSOR FOR SELECT asn."Id",asn."UserId",asn."ActivityId",pd."DataSourceId",ad."Dump"::TEXT
FROM "Development"."ActivitySession" as asn inner join "Development"."PersonDataSource" as pd on pd."UserId" = asn."UserId" inner join "Development"."ActivitySessionDump" as ad
on asn."Id"=ad."ActivitySessionId" where asn."CreatedAt" between now() - interval '5 days' and now() and asn."ActivityId"=1 and pd."DataSourceId"=1 for read only;
titles TEXT DEFAULT '';
rec record;
jsonrec record;
BEGIN
OPEN sessionid;
loop
FETCH sessionid INTO rec;
--raise notice '%d',rec."UserId";
if not found then
exit ;
end if;
EXECUTE 'SELECT rec."Dump"::json#>''{activities-steps,0}''->>''value'' as steps ' INTO jsonrec;
titles := titles || ',' || jsonrec."steps";
end loop;
return titles;
END;
$$ LANGUAGE plpgsql;
据我所知,循环或函数是不必要的。它可以替换为使用字符串聚合的简单查询:
SELECT string_agg("Dump"->'activities-steps'->0->'value', ',') as steps
FROM "ActivitySessionDump" d
WHERE d."ActivitySessionId" IN (SELECT asn."Id"
FROM "ActivitySession" as asn
join "PersonDataSource" as pd on pd."UserId" = asn."UserId"
where asn."CreatedAt" between now() - interval '5 days' and now()
and asn."ActivityId" = 1
and pd."DataSourceId" = 1);
无关,但是:你应该真的避免那些可怕的引用标识符