【问题标题】:Oracle PL/SQL Pass row type as constructor parameterOracle PL/SQL 传递行类型作为构造函数参数
【发布时间】: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”的主体 错误:检查编译器日志

这样的事情可能吗?

【问题讨论】:

  • 显然不是。我建议传入相关行的主键,然后在函数中获取所需的行。

标签: oracle plsql oracle-sqldeveloper


【解决方案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 分配字段的子集,您可以这样做

    1. 定义构造方法
    CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, ctrl shape) RETURN SELF AS RESULT,
    
    1. 或者简单地定义另一个包含您需要的字段的对象,并在您的构造函数中使用 %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 方法非常相似,但没有基于对象记录的表

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多