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



我声明了一个带有2个参数的构造函数的对象。我不能使用它,因为oracle返回:

[Error] execute (2:10): ORA-06553: PLS-307: too many declarations .

  • 我没有声明这个构造函数超过一次。

  • 我的代码是工作在db小提琴,但不是在我的数据库。dbfiddle上的代码和我的代码之间唯一的区别是这个对象有一个所有者。

  • 因此对象的名称是这样定义的:owner_name.object_name.

  • 我已经检查了对象是否在另一个所有者中定义。当我调用构造函数时,我使用owner_name.constructor

  • 我已经创建了一个虚拟的构造函数,它接受0个参数,它工作。

_

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] execute (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

您的代码在Oracle 21c下运行时可以在db<>fiddle中工作,但在Oracle 18c或11g下就不能了。

你说你没有声明构造函数超过一次,但你有;有一个具有相同参数的默认构造函数-来自19c文档:

数据库隐式地为您创建的每个用户定义类型定义了一个构造函数方法。构造函数是系统提供的过程,在SQL语句或PL/SQL代码中用于构造类型value的实例。构造函数方法的名称是用户定义类型的名称。您还可以使用constructor_spec语法创建用户定义的构造函数。

:

默认情况下,系统隐式地为所有具有属性的对象类型定义了构造函数。

系统定义的构造函数有时被称为属性值构造函数。

您正在创建一个用户定义的构造函数,但它与隐式构造函数具有相同的定义。嗯,几乎。

19c还表示:

如果用户定义的构造函数的签名与属性值构造函数的签名完全匹配,则用户定义的构造函数将隐藏其类型的属性值构造函数,从而取代属性值构造函数。

为了使签名匹配,用户自定义构造函数的参数名称和类型(在隐式SELF形参之后)必须与该类型的属性名称和类型相同。

在18c中,如果您更改参数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似乎更宽容/灵活,尽管文档没有改变。(或者可能19c,或者它的某个版本,也允许这样做-我只是在db<>fiddle..)

然而,因为你在这里所做的只是一个简单的赋值,所以在任何版本中都不需要重写构造函数——没有它也可以工作。

在我将未声明的构造函数添加到规范之后,它编译并正常工作:

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<此处小提琴>

最新更新