【问题标题】:cursor loop in PostgreSQLPostgreSQL 中的游标循环
【发布时间】:2017-02-28 16:28:27
【问题描述】:

以下代码是 PostgreSQL 9.0 中的游标。我想通过加入多个表来获取我的记录,并且我正在从该连接中获取 JSON 数据。

所以我想循环这些记录并使用类似于

的查询来解析该 json
SELECT "Dump"->'activities-steps'->0->'value' as "steps"
FROM "ActivitySessionDump" where "Id"=42594321345021288   

然后我必须从此查询中获取数据并插入到其他表中,例如

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;

非常感谢任何帮助。谢谢

【问题讨论】:

  • 您的问题到底是什么?请发布您的函数的完整源代码。
  • 在我的代码中我给出了一些注释,即我想在游标声明后启动一个循环并执行一个 sql 并插入到某个表中
  • 我没有创建任何函数,我只想创建一个光标
  • 你不能像在函数外那样运行 PL/pgSQL 块。如果你不想要一个函数,你需要使用do 块:postgresql.org/docs/9.0/static/sql-do.html 但是你为什么不能简单地使用insert into table (key, value) select ...
  • 此外,不再维护或支持 Postgres 9.0。您确实需要尽快计划升级。

标签: json postgresql cursor plpgsql


【解决方案1】:

由于您无法在 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 ...);

【讨论】:

  • 非常感谢您的建议,但我的代码工作正常。
【解决方案2】:

这是我的问题的代码,我无法 EXECUTE 'SELECT rec."Dump"::json#>''{activities-steps,0}''->>''value'' as steps ' 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 语句替换。
  • 不,我需要在执行该 sql 语句(SELECT "Dump"->''activities-steps''->0->''value'')之前检查一些东西,结果需要插入某处.
  • 如果你想插入结果,使用insert into ... select ... 并且你的函数不会做任何“执行前检查”。如果不能将该检查作为where 条件集成到 SELECT 语句中,我也不会感到惊讶。
  • 您好,请帮忙link
【解决方案3】:

据我所知,循环或函数是不必要的。可以用字符串聚合的简单查询替换它:

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);

不相关,但是:你应该真的避免使用那些可怕的带引号的标识符

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-18
    • 2016-02-12
    • 2012-03-27
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    相关资源
    最近更新 更多