Oracle PL/SQL 传递行类型作为构造函数参数
Posted
技术标签:
【中文标题】Oracle PL/SQL 传递行类型作为构造函数参数【英文标题】:Oracle PL/SQL Pass row type as constructor parameter 【发布时间】:2020-11-22 17:44:54 【问题描述】:是否可以在构造函数中将 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;
/
行/列错误
0/0 PL/SQL:编译单元分析终止 8/63 PLS-00329:模式级类型对 SCHEMA_A.CONTROL 的引用非法 错误:检查编译器日志
类型 Body SHAPE 编译
行/列错误
0/0 PL/SQL:编译单元分析终止 1/11 PLS-00905:对象 SCHEMA_A.SHAPE 无效 1/11 PLS-00304:没有规范就无法编译“SHAPE”的主体 错误:检查编译器日志
这样的事情可能吗?
【问题讨论】:
显然不是。我建议传入相关行的主键,然后在函数中获取所需的行。 【参考方案1】:如果你想采取稍微不同的方法,你可以创建一个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;
然后,您可以传递该表的基础对象类型,而不是期望光标中有 %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;
/
然后您可以在对象表的SELECT
中使用VALUE(column_alias)
将表的基础对象类型传递给您的构造函数:
SELECT s.shape.area,
s.shape.name
FROM (
SELECT SHAPE(VALUE(c)) AS shape
FROM control c
) s;
输出:
形状面积 |形状名称 ---------: | :--------- 42 |正方形
db小提琴here
【讨论】:
【参考方案2】:如果此记录类型仅以 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 方法非常相似,但没有基于对象记录的表
【讨论】:
以上是关于Oracle PL/SQL 传递行类型作为构造函数参数的主要内容,如果未能解决你的问题,请参考以下文章
插入行类型记录,该记录在Oracle中的PL / SQL中作为参数传递。我该如何实现?
如何在 Java 中构造 oracle.sql.ANYDATA 并在 PL/SQL 过程中传递它
从 pl/sql 中的函数返回数据作为光标而不创建类型 oracle 11g