在 PostgreSQL 中迭代和动态更改类型元素
Iterating and Dynamically Changing Elements of Type in PostgreSQL
我最近被要求将数据库从 Oracle 迁移到 Postgres(在这件事上我没有真正的选择)。使用 ora2pg 工具,我已经成功地迁移了大部分 DDL,但是当我接触到一些 PL/SQL 代码时真正的头疼开始了。
把事情简单化了,这里有一些代码代表了我的大部分问题(类似的问题出现在代码的多个部分)。
sql_statement := 'SELECT * FROM TABLE_1';
OPEN ref_cursor FOR sql_statement;
FETCH ref_cursor BULK COLLECT INTO list_a_aux;
WHILE list_a_aux.COUNT <> 0
LOOP
FOR n in list_a_aux.FIRST..list_a_aux.LAST
LOOP
IF list_a_aux(n).id = 0 THEN
list_a.EXTEND;
list_a(list_a.COUNT).id = 1;
list_a_aux.DELETE(n);
ELSE
-- More Application Logic
END IF;
END LOOP;
END LOOP;
list_a 和 list_a_aux 都初始化为:
list_a list_a:= list_a();
list_a_aux list_a:= list_a();
其中 list_a 是声明为的类型:
TYPE list_a IS TABLE OF TABLE_2;
我 运行 进入的第一个问题是 "BULK COLLECT" 声明。我搜索了一些邮件列表,我被指向 HERE。
我理解了解决方案,它看起来很简单,但后来我深入研究了代码,我无法弄清楚如何将它与其余代码集成。我已经尝试搜索与此代码中存在的问题类似的问题,并且我找到了许多个别问题(1,2 等)的解决方案,但 none 似乎适合这个特定问题(即使结合起来也不行!)。
关于如何迁移这段 PL/SQL 的任何想法?
是的,PostgreSQL中没有BULK COLLECT
;你以一种不同的(甚至更简单的)方式处理事情。
如您所见,您可以像这样循环查询结果:
FOR rec_var IN SELECT ... LOOP
<statements>
END LOOP;
如果您需要对象集合,您可以使用数组——在您的示例中您可以使用
DECLARE
list_a table_2[] := ARRAY[]::table_2[];
声明一个数组并将其初始化为空数组。有大量的 array functions and operators 来操纵它们。您只需分配给新的下标或使用 array_append()
即可扩展它们。没有删除特定索引处元素的函数,但您可以通过连接元素前后的切片来创建新数组,或者更改逻辑以对已删除的元素使用 NULL
。
但是,您通常可以编写代码,这样您就不需要使用对象集合。您可以使用 table 函数(Oracle 中的 PIPELINED
函数)一次传递一个结果。当然,这并不总是可能的,并且可能需要大量重写,如果您的目标是迁移现有代码,您可能不会这样做。
我最近被要求将数据库从 Oracle 迁移到 Postgres(在这件事上我没有真正的选择)。使用 ora2pg 工具,我已经成功地迁移了大部分 DDL,但是当我接触到一些 PL/SQL 代码时真正的头疼开始了。
把事情简单化了,这里有一些代码代表了我的大部分问题(类似的问题出现在代码的多个部分)。
sql_statement := 'SELECT * FROM TABLE_1';
OPEN ref_cursor FOR sql_statement;
FETCH ref_cursor BULK COLLECT INTO list_a_aux;
WHILE list_a_aux.COUNT <> 0
LOOP
FOR n in list_a_aux.FIRST..list_a_aux.LAST
LOOP
IF list_a_aux(n).id = 0 THEN
list_a.EXTEND;
list_a(list_a.COUNT).id = 1;
list_a_aux.DELETE(n);
ELSE
-- More Application Logic
END IF;
END LOOP;
END LOOP;
list_a 和 list_a_aux 都初始化为:
list_a list_a:= list_a();
list_a_aux list_a:= list_a();
其中 list_a 是声明为的类型:
TYPE list_a IS TABLE OF TABLE_2;
我 运行 进入的第一个问题是 "BULK COLLECT" 声明。我搜索了一些邮件列表,我被指向 HERE。 我理解了解决方案,它看起来很简单,但后来我深入研究了代码,我无法弄清楚如何将它与其余代码集成。我已经尝试搜索与此代码中存在的问题类似的问题,并且我找到了许多个别问题(1,2 等)的解决方案,但 none 似乎适合这个特定问题(即使结合起来也不行!)。
关于如何迁移这段 PL/SQL 的任何想法?
是的,PostgreSQL中没有BULK COLLECT
;你以一种不同的(甚至更简单的)方式处理事情。
如您所见,您可以像这样循环查询结果:
FOR rec_var IN SELECT ... LOOP
<statements>
END LOOP;
如果您需要对象集合,您可以使用数组——在您的示例中您可以使用
DECLARE
list_a table_2[] := ARRAY[]::table_2[];
声明一个数组并将其初始化为空数组。有大量的 array functions and operators 来操纵它们。您只需分配给新的下标或使用 array_append()
即可扩展它们。没有删除特定索引处元素的函数,但您可以通过连接元素前后的切片来创建新数组,或者更改逻辑以对已删除的元素使用 NULL
。
但是,您通常可以编写代码,这样您就不需要使用对象集合。您可以使用 table 函数(Oracle 中的 PIPELINED
函数)一次传递一个结果。当然,这并不总是可能的,并且可能需要大量重写,如果您的目标是迁移现有代码,您可能不会这样做。