如何将对象类型属性的值分配给plsql中具有相同属性属性的不同对象类型?
How to assign values of object type attributes to different object type with same attribute properties in plsql?
我有两种具有相同属性的不同类型。我需要将第一种类型的属性值分配给其他类型。除了架构和对象名称外,它们完全相同。
CREATE OR REPLACE TYPE SCHEMA_A.type_A AS OBJECT(XCOL VARCHAR2(80), YCOL VARCHAR2(80), ZCOL CHAR(2));
CREATE OR REPLACE TYPE SCHEMA_B.type_B AS OBJECT(XCOL VARCHAR2(80), YCOL VARCHAR2(80), ZCOL CHAR(2));
我可以像下面那样手动给一个值赋值,但实际上有超过 80 个属性。有没有更优雅的方式达到同样的效果?
SCHEMA_A.type_A.XCOL := SCHEMA_B.type_B.XCOL;
SCHEMA_A.type_A.YCOL := SCHEMA_B.type_B.YCOL;
...
AFAIK 您几乎无法完成 attribute-by-attribute 作业。这是创建 2 个相同类型的 by-product - 这是你的主要错误。但是有两种可能的解决方案:
- 创建一个只有一种类型的通用模式,然后更新引用
到通用模式。
- 编写一个函数,将 2 种类型作为参数,source 和
目的地,并执行 attribute-by-attribute 复制。你的代码
然后调用函数。
正如他在回答 中提到的,最好的解决方案是为两种方案创建一个通用数据类型。
快速而肮脏的解决方案是使用 SQL 查询进行转换。查看以下可重现的示例:
create or replace type A.objA as object (attr1 varchar2 (8), attr2 int, attr3 date)
/
create or replace type B.objB as object (attr1 varchar2 (8), attr2 int, attr3 date);
/
create or replace type A.objtA as table of A.objA;
/
create or replace type A.objtB as table of B.objB;
/
var rc refcursor
declare
a A.objA;
b B.objB := B.objB ('name B', 1, trunc (sysdate));
function cast (o B.objB) return A.objA is
t A.objtA;
begin
select cast (multiset (select * from A.objtB (b))
as A.objtA) into t from dual;
return t(1);
end;
begin
a := cast (b);
open :rc for select a a from dual;
end;
/
A(ATTR1, ATTR2, ATTR3)
------------------------------------------------
OBJA('name B', 1, '2020-10-18 00:00:00')
由于类型是模式对象,它们具有默认构造函数,可以稍微简化赋值:
declare
v_type_a type_a := type_a('a', 'a', 'a');
v_type_b type_b := type_b('b', 'b', 'b');
begin
v_type_a := type_a(v_type_b.xcol, v_type_b.ycol, v_type_b.zcol);
end;
/
在 18c 及更高版本中,由于新的限定表达式功能,相同的想法甚至适用于 PL/SQL-only 类型。
如果只有两种类型,那么上述快捷方式可能是您最好的选择。如果您有多组类型需要分配,请告诉我们;在这种情况下,可能值得花费额外的精力使用 ANYDATA 或使用数据字典动态构建函数来构建解决方案。
我有两种具有相同属性的不同类型。我需要将第一种类型的属性值分配给其他类型。除了架构和对象名称外,它们完全相同。
CREATE OR REPLACE TYPE SCHEMA_A.type_A AS OBJECT(XCOL VARCHAR2(80), YCOL VARCHAR2(80), ZCOL CHAR(2));
CREATE OR REPLACE TYPE SCHEMA_B.type_B AS OBJECT(XCOL VARCHAR2(80), YCOL VARCHAR2(80), ZCOL CHAR(2));
我可以像下面那样手动给一个值赋值,但实际上有超过 80 个属性。有没有更优雅的方式达到同样的效果?
SCHEMA_A.type_A.XCOL := SCHEMA_B.type_B.XCOL;
SCHEMA_A.type_A.YCOL := SCHEMA_B.type_B.YCOL;
...
AFAIK 您几乎无法完成 attribute-by-attribute 作业。这是创建 2 个相同类型的 by-product - 这是你的主要错误。但是有两种可能的解决方案:
- 创建一个只有一种类型的通用模式,然后更新引用 到通用模式。
- 编写一个函数,将 2 种类型作为参数,source 和 目的地,并执行 attribute-by-attribute 复制。你的代码 然后调用函数。
正如他在回答
快速而肮脏的解决方案是使用 SQL 查询进行转换。查看以下可重现的示例:
create or replace type A.objA as object (attr1 varchar2 (8), attr2 int, attr3 date)
/
create or replace type B.objB as object (attr1 varchar2 (8), attr2 int, attr3 date);
/
create or replace type A.objtA as table of A.objA;
/
create or replace type A.objtB as table of B.objB;
/
var rc refcursor
declare
a A.objA;
b B.objB := B.objB ('name B', 1, trunc (sysdate));
function cast (o B.objB) return A.objA is
t A.objtA;
begin
select cast (multiset (select * from A.objtB (b))
as A.objtA) into t from dual;
return t(1);
end;
begin
a := cast (b);
open :rc for select a a from dual;
end;
/
A(ATTR1, ATTR2, ATTR3)
------------------------------------------------
OBJA('name B', 1, '2020-10-18 00:00:00')
由于类型是模式对象,它们具有默认构造函数,可以稍微简化赋值:
declare
v_type_a type_a := type_a('a', 'a', 'a');
v_type_b type_b := type_b('b', 'b', 'b');
begin
v_type_a := type_a(v_type_b.xcol, v_type_b.ycol, v_type_b.zcol);
end;
/
在 18c 及更高版本中,由于新的限定表达式功能,相同的想法甚至适用于 PL/SQL-only 类型。
如果只有两种类型,那么上述快捷方式可能是您最好的选择。如果您有多组类型需要分配,请告诉我们;在这种情况下,可能值得花费额外的精力使用 ANYDATA 或使用数据字典动态构建函数来构建解决方案。