Oracle PL/SQL 将行类型作为构造函数参数传递
Oracle PL/SQL Pass row type as constructor parameter
是否可以在构造函数中将 table%rowtype 作为参数传递?
我有这样的东西,而且有效
CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY shape AS
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
RETURN;
END;
END;
/
但是我还需要传递一个 table%row 作为参数
CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl CONTROL%ROWTYPE) RETURN SELF AS RESULT
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY shape AS
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl CONTROL%ROWTYPE) RETURN SELF AS RESULT IS
BEGIN
SELF.area := NULL;
RETURN;
END;
END;
/
LINE/COL错误
0/0 PL/SQL: 编译单元分析终止
8/63 PLS-00329:模式级类型对 SCHEMA_A.CONTROL 有非法引用
错误:检查编译器日志
编译体型
LINE/COL错误
0/0 PL/SQL: 编译单元分析终止
1/11 PLS-00905:对象 SCHEMA_A.SHAPE 无效
1/11 PLS-00304:无法编译没有规范的 'SHAPE' 的主体
错误:检查编译器日志
这样的事情可能吗?
如果你想采用稍微不同的方法,你可以创建一个 object table:
CREATE TYPE control_type AS OBJECT (
id NUMBER(8,0),
name VARCHAR2(30),
area NUMBER
);
CREATE TABLE control OF control_type(
CONSTRAINT control__id__pk PRIMARY KEY (id)
);
INSERT INTO control (id, name, area)
SELECT 1, 'square', 42 FROM DUAL;
然后您可以传递 table:
的基础对象类型,而不是期望光标中出现 %ROWTYPE
CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl control_type) RETURN SELF AS RESULT
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY shape AS
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl control_type) RETURN SELF AS RESULT IS
BEGIN
SELF.name := ctrl.name;
SELF.area := ctrl.area;
RETURN;
END;
END;
/
然后您可以在对象 table 的 SELECT
中使用 VALUE(column_alias)
将 table 的基础对象类型传递给您的构造函数:
SELECT s.shape.area,
s.shape.name
FROM (
SELECT SHAPE(VALUE(c)) AS shape
FROM control c
) s;
输出:
SHAPE.AREA | SHAPE.NAME
---------: | :---------
42 | square
db<>fiddle here
如果此记录类型仅分配字段的子集1:1你可以这样做
- 定义构造方法
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl shape) RETURN SELF AS RESULT,
- 或者简单地用您需要的字段定义另一个对象,并在您的构造函数中使用它代替 %rowtype
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl t_control_rec) RETURN SELF AS RESULT,
这是记录类型定义
CREATE TYPE t_control_rec AS OBJECT (
id NUMBER
name VARCHAR2(30),
area NUMBER
);
/
这是第一种方法的演示:
SET SERVEROUTPUT ON;
DECLARE
l_base_shape shape := shape('square', 42);
l_ctrl_shape shape; --l_control_rec t_control_rec;
BEGIN
l_base_shape.display();
WITH imaginary_table AS (
SELECT 1 id, 'tesseract' name, 2048 area
FROM dual
)
SELECT shape(it.name, it.area) --t_control_rec(it.name, it.area)
INTO l_ctrl_shape
FROM imaginary_table it;
l_ctrl_shape.display();
l_base_shape := shape(l_ctrl_shape);
l_base_shape.display();
END;
/
添加了额外的方法 shape.display()
member procedure display is
begin
dbms_output.put_line(self.name|| ':'|| self.area);
end;
*它与@MT0 方法非常相似,但没有 table 和基于对象的记录
是否可以在构造函数中将 table%rowtype 作为参数传递?
我有这样的东西,而且有效
CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY shape AS
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
RETURN;
END;
END;
/
但是我还需要传递一个 table%row 作为参数
CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl CONTROL%ROWTYPE) RETURN SELF AS RESULT
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY shape AS
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl CONTROL%ROWTYPE) RETURN SELF AS RESULT IS
BEGIN
SELF.area := NULL;
RETURN;
END;
END;
/
LINE/COL错误
0/0 PL/SQL: 编译单元分析终止 8/63 PLS-00329:模式级类型对 SCHEMA_A.CONTROL 有非法引用 错误:检查编译器日志
编译体型
LINE/COL错误
0/0 PL/SQL: 编译单元分析终止 1/11 PLS-00905:对象 SCHEMA_A.SHAPE 无效 1/11 PLS-00304:无法编译没有规范的 'SHAPE' 的主体 错误:检查编译器日志
这样的事情可能吗?
如果你想采用稍微不同的方法,你可以创建一个 object table:
CREATE TYPE control_type AS OBJECT (
id NUMBER(8,0),
name VARCHAR2(30),
area NUMBER
);
CREATE TABLE control OF control_type(
CONSTRAINT control__id__pk PRIMARY KEY (id)
);
INSERT INTO control (id, name, area)
SELECT 1, 'square', 42 FROM DUAL;
然后您可以传递 table:
的基础对象类型,而不是期望光标中出现%ROWTYPE
CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl control_type) RETURN SELF AS RESULT
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY shape AS
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2)
RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2,
area NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
RETURN;
END;
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl control_type) RETURN SELF AS RESULT IS
BEGIN
SELF.name := ctrl.name;
SELF.area := ctrl.area;
RETURN;
END;
END;
/
然后您可以在对象 table 的 SELECT
中使用 VALUE(column_alias)
将 table 的基础对象类型传递给您的构造函数:
SELECT s.shape.area,
s.shape.name
FROM (
SELECT SHAPE(VALUE(c)) AS shape
FROM control c
) s;
输出:
SHAPE.AREA | SHAPE.NAME ---------: | :--------- 42 | square
db<>fiddle here
如果此记录类型仅分配字段的子集1:1你可以这样做
- 定义构造方法
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl shape) RETURN SELF AS RESULT,
- 或者简单地用您需要的字段定义另一个对象,并在您的构造函数中使用它代替 %rowtype
CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl t_control_rec) RETURN SELF AS RESULT,
这是记录类型定义
CREATE TYPE t_control_rec AS OBJECT (
id NUMBER
name VARCHAR2(30),
area NUMBER
);
/
这是第一种方法的演示:
SET SERVEROUTPUT ON;
DECLARE
l_base_shape shape := shape('square', 42);
l_ctrl_shape shape; --l_control_rec t_control_rec;
BEGIN
l_base_shape.display();
WITH imaginary_table AS (
SELECT 1 id, 'tesseract' name, 2048 area
FROM dual
)
SELECT shape(it.name, it.area) --t_control_rec(it.name, it.area)
INTO l_ctrl_shape
FROM imaginary_table it;
l_ctrl_shape.display();
l_base_shape := shape(l_ctrl_shape);
l_base_shape.display();
END;
/
添加了额外的方法 shape.display()
member procedure display is
begin
dbms_output.put_line(self.name|| ':'|| self.area);
end;
*它与@MT0 方法非常相似,但没有 table 和基于对象的记录