与此调用匹配的构造声明过多

too many declaration of a construct match this call

我已经声明了一个带有两个参数的构造函数的对象。我不能使用它,因为 oracle returns:

[Error] Execution (2: 10): ORA-06553: PLS-307: too many declarations of 'BOUNDARY' match this call

_

CREATE OR REPLACE TYPE my_user.boundary AS OBJECT
(
    v_start INTEGER,
    v_end INTEGER,
    CONSTRUCTOR FUNCTION boundary (i_start INTEGER, i_end INTEGER)
        RETURN SELF AS RESULT,
    MEMBER FUNCTION isInside (i INTEGER)
        RETURN INTEGER
);

CREATE OR REPLACE TYPE BODY my_user.boundary
AS
    CONSTRUCTOR FUNCTION boundary 
        RETURN SELF AS RESULT
    IS
    BEGIN
        v_start := 1;
        v_end := 2;
        RETURN;
    END;
    
    CONSTRUCTOR FUNCTION boundary (i_start INTEGER, i_end INTEGER)
        RETURN SELF AS RESULT
    IS
    BEGIN
        v_start := i_start;
        v_end := i_end;
        RETURN;
    END;

    MEMBER FUNCTION isInside (i INTEGER)
        RETURN INTEGER
    IS
    BEGIN
        IF v_start <= i AND i <= v_end
        THEN
            RETURN 1;
        ELSE
            RETURN 0;
        END IF;
    END;
END;

SELECT ( my_user.boundary(1,2)) FROM DUAL; --doesn't work

[Error] Execution (2: 10): ORA-06553: PLS-307: too many declarations of 'BOUNDARY' match this call

SELECT ( my_user.boundary()).isInside(1) FROM DUAL; --is working

1

在我将未声明的构造函数添加到规范后,它编译并运行良好:

CREATE OR REPLACE TYPE BV_OWN.boundary AS OBJECT
(
    v_start INTEGER,
    v_end INTEGER,
    CONSTRUCTOR FUNCTION boundary   -- added
        RETURN SELF AS RESULT,
    CONSTRUCTOR FUNCTION boundary (i_start INTEGER, i_end INTEGER)
        RETURN SELF AS RESULT,
    MEMBER FUNCTION isInside (i INTEGER)
        RETURN INTEGER
);

不得不放弃模式规范,因为我没有 BV_OWN 用户来测试。使用 Oracle 21c。 db<>fiddle here

当 运行 under Oracle 21c, but not under 18c 或 11g 时,您的代码在 db<>fiddle 中有效。

你说你没有多次声明构造函数,但你有点有;有一个具有相同参数的默认构造函数 - from the 19c doc:

The database implicitly defines a constructor method for each user-defined type that you create. A constructor is a system-supplied procedure that is used in SQL statements or in PL/SQL code to construct an instance of the type value. The name of the constructor method is the name of the user-defined type. You can also create a user-defined constructor using the constructor_spec syntax.

and:

By default, the system implicitly defines a constructor function for all object types that have attributes.

A system-defined constructor is sometimes known as the attribute value constructor.

您正在创建一个 user-defined 构造函数,但它与隐式构造函数具有相同的定义。嗯,差不多。

19c also says:

a user-defined constructor does hide, and thus supersede, the attribute-value constructor for its type if the signature of the user-defined constructor exactly matches the signature of the attribute-value constructor.

For the signatures to match, the names and types of the parameters (after the implicit SELF parameter) of the user-defined constructor must be the same as the names and types of the attributes of the type.

在 18c 中 it works 如果更改参数 names 以匹配属性名称:

CREATE OR REPLACE TYPE boundary AS OBJECT
(
    v_start INTEGER,
    v_end INTEGER,
    CONSTRUCTOR FUNCTION boundary (v_start INTEGER, v_end INTEGER)
        RETURN SELF AS RESULT,
    MEMBER FUNCTION isInside (i INTEGER)
        RETURN INTEGER
);
/

CREATE OR REPLACE TYPE BODY boundary
AS
    CONSTRUCTOR FUNCTION boundary (v_start INTEGER, v_end INTEGER)
        RETURN SELF AS RESULT
    IS
    BEGIN
        SELF.v_start := v_start;
        SELF.v_end := v_end;
        RETURN;
    END;
...

21c 似乎更 forgiving/flexible,尽管文档 hasn't changed。 (或者也许 19c 或它的某些版本也允许这样做 - 我只是继续 db<>fiddle..)

中的可用版本

但是,由于您在这里所做的只是一个简单的赋值,您不需要任何版本的重写构造函数 - it works without it