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

如何使用 jOOQ 将 Oracle PL/SQL 常量作为参数传递?

在纯 Oracle SQL 中选择所有行作为一个表类型对象

Oracle CREATE TYPE 和 PL/SQL