postgresql - 在 postgres 中使用光标批量收集
问题描述
我们正在从 Oracle 迁移到 Postgres。我有下一个代码。我被批量收集光标困住了。我尝试使用 insert into .. select * from.. 但是当这段代码检查某些特定列时,我很困惑。
创建或替换函数 usmqa.pk_vpdata_load_load_vdrarmhlink(输出 err_code bigint,输出 vdrarmhlink_errmsg 文本)返回记录语言“plpgsql”
$BODY$ 声明
V_COUNT_VDRARMHLINK bigint;
CUR_GET_INT_VDRARMHLINK CURSOR FOR
SELECT VENLINKID,
VENARINTNO,
VENMVINTNO,
VENLINKEFFDT,
VENLINKTRMDT,
VENACT,
VENRUNSTS,
VENPROCID,
VENERRCODE
FROM INT_VDRARMHLINK
WHERE VENRUNSTS = -1
AND coalesce(VENERRMSG::text, '') = ''
AND coalesce(VENERRCODE::text, '') = '';
-- TYPE TYP_GET_INT_VDRARMHLINK IS TABLE OF RECORD INDEX BY integer; Oracle code
--REC_GET_INT_VDRARMHLINK TYP_GET_INT_VDRARMHLINK; --- Oracle
REC_GET_INT_VDRARMHLINK int[];
I int;
BEGIN
glo_error_var:= 0;
UPDATE INT_VDRARMHLINK SET VENRUNSTS = -1 WHERE VENRUNSTS = 0;
glo_error_var:= 1;
UPDATE INT_VDRARMHLINK
SET VENERRMSG = 'VENDOR INTERNAL NUMBER DOES NOT EXISTS VDREXT TABLE',
VENERRCODE = -1,
VENRUNSTS = -2
WHERE NOT EXISTS (SELECT 1 FROM VDREXT WHERE VDXINTNO = VENARINTNO)
OR NOT EXISTS (SELECT 1 FROM VDREXT WHERE VDXINTNO = VENMVINTNO);
COMMIT;
glo_error_var:= 2;
OPEN CUR_GET_INT_VDRARMHLINK;
LOOP
-- FETCH CUR_GET_INT_VDRARMHLINK BULK COLLECT ---- Oracle code
-- INTO REC_GET_INT_VDRARMHLINK LIMIT 1000; ---- Oracle code
-- FOR I IN 1 .. REC_GET_INT_VDRARMHLINK.COUNT LOOP -- Oracle code
SELECT arrat_agg(CUR_GET_INT_VDRARMHLINK)
into REC_GET_INT_VDRARMHLINK
FROM CUR_GET_INT_VDRARMHLINK;
FOREACH I SLICE 1 in ARRAY REC_GET_INT_VDRARMHLINK
LOOP
BEGIN
SELECT COUNT(1)
INTO STRICT V_COUNT_VDRARMHLINK
FROM VDRARMHLINK
WHERE VENARINTNO = REC_GET_INT_VDRARMHLINK[I].VENARINTNO
AND VENMVINTNO = REC_GET_INT_VDRARMHLINK[I].VENMVINTNO;
END;
--INSERT
IF ( V_COUNT_VDRARMHLINK = 0 AND
REC_GET_INT_VDRARMHLINK[I].VENRUNSTS = -1) THEN
SELECT VENLINKID,
VENARINTNO,
VENMVINTNO,
VENLINKEFFDT,
VENLINKTRMDT,
VENACT,
VENRUNSTS,
VENPROCID,
VENERRCODE
FROM INT_VDRARMHLINK
WHERE VENRUNSTS = -1
AND coalesce(VENERRMSG::text, '') = ''
AND coalesce(VENERRCODE::text, '') = '';
BEGIN
INSERT INTO VDRARMHLINK
(VENLINKID,
VENARINTNO,
VENMVINTNO,
VENLINKEFFDT,
VENLINKTRMDT)
VALUES (REC_GET_INT_VDRARMHLINK[I].VENLINKID,
REC_GET_INT_VDRARMHLINK[I].VENARINTNO,
REC_GET_INT_VDRARMHLINK[I].VENMVINTNO,
REC_GET_INT_VDRARMHLINK[I].VENLINKEFFDT,
REC_GET_INT_VDRARMHLINK[I].VENLINKTRMDT);
UPDATE INT_VDRARMHLINK
SET VENRUNSTS = 1
WHERE
VENPROCID = REC_GET_INT_VDRARMHLINK[I].VENPROCID
AND VENERRCODE = NULL
AND VENERRMSG = NULL;
END;
END IF;
IF (V_COUNT_VDRARMHLINK = 1) THEN
BEGIN
UPDATE VDRARMHLINK
SET VENLINKEFFDT = REC_GET_INT_VDRARMHLINK[I].VENLINKEFFDT,
VENLINKTRMDT = REC_GET_INT_VDRARMHLINK[I].VENLINKTRMDT
WHERE VENLINKID = REC_GET_INT_VDRARMHLINK[I].VENLINKID
AND VENARINTNO = REC_GET_INT_VDRARMHLINK[I].VENARINTNO
AND VENMVINTNO = REC_GET_INT_VDRARMHLINK[I].VENMVINTNO;
UPDATE INT_VDRARMHLINK
SET VENRUNSTS = 1
WHERE VENPROCID = REC_GET_INT_VDRARMHLINK[I]
.VENPROCID
AND VENLINKID = REC_GET_INT_VDRARMHLINK[I]
.VENLINKID
AND VENARINTNO = REC_GET_INT_VDRARMHLINK[I]
.VENARINTNO
AND VENMVINTNO = REC_GET_INT_VDRARMHLINK[I]
.VENMVINTNO
AND VENERRCODE = NULL
AND VENERRMSG = NULL;
END;
END IF;
--DELETE
IF (REC_GET_INT_VDRARMHLINK[I].VENACT = 2 AND V_COUNT_VDRARMHLINK = 1) THEN
BEGIN
UPDATE VDRARMHLINK
SET VENLINKEFFDT = REC_GET_INT_VDRARMHLINK[I].VENLINKEFFDT,
VENLINKTRMDT = clock_timestamp()
WHERE VENLINKID = REC_GET_INT_VDRARMHLINK[I]
.VENLINKID
AND VENARINTNO = REC_GET_INT_VDRARMHLINK[I]
.VENARINTNO
AND VENMVINTNO = REC_GET_INT_VDRARMHLINK[I].VENMVINTNO;
UPDATE INT_VDRARMHLINK
SET VENRUNSTS = 1
WHERE VENACT = 2
AND VENPROCID = REC_GET_INT_VDRARMHLINK[I]
.VENPROCID
AND VENLINKID = REC_GET_INT_VDRARMHLINK[I]
.VENLINKID
AND VENARINTNO = REC_GET_INT_VDRARMHLINK[I]
.VENARINTNO
AND VENMVINTNO = REC_GET_INT_VDRARMHLINK[I]
.VENMVINTNO
AND VENERRCODE = NULL
AND VENERRMSG = NULL;
ELSIF (REC_GET_INT_VDRARMHLINK[I]
.VENACT = 2 AND V_COUNT_VDRARMHLINK = 0) THEN
UPDATE INT_VDRARMHLINK
SET VENRUNSTS = -3,
VENERRCODE = -300,
VENERRMSG = 'THERE IS NO VENODR AR MERCHANDISE IN VP TO DELETE'
WHERE VENACT = 2
AND VENPROCID = REC_GET_INT_VDRARMHLINK[I]
.VENPROCID
AND VENERRCODE = NULL
AND VENERRMSG = NULL;
END IF;
END LOOP;
EXIT WHEN NOT FOUND; /* apply on CUR_GET_INT_VDRARMHLINK */
END LOOP;
CLOSE CUR_GET_INT_VDRARMHLINK;
END;
$BODY$;
解决方案
Although PL/PGSQL has cursors similar to Oracle PL/SQL, there is no BULK COLLECT statement in PL/PGSQL.
When porting Oracle PL/SQL code to PostgreSQL PL/PGSQL code, see Porting from Oracle PL/SQL documentation.
推荐阅读
- swift - 如何在 Swift 中访问结构指针的属性/成员
- flutter - 如何解决此错误: Struct 'Utf8' 为空。不推荐使用对空结构的支持...改用不透明
- powerquery - 在 Power Query 中组合匹配名称模式的表
- google-chrome-extension - 如何将 Chrome 扩展移植到 Firefox 插件?
- c++ - 有没有可能使用转换的迭代器获取原始值的方法?
- java - 使用 JWT 令牌的 jti 声明作为不透明令牌
- c - 在c中的文本文件中过滤查询
- c# - Entity Framework Core 在使用自有类型时尝试加入不存在的表
- javascript - 如何从样式组件中的另一个文件继承元素的样式
- reactjs - 成功登录后可以从 Reactjs 中的数据库加载配置数据吗?