如何在Oracle 11g中调试用户定义的聚合函数?

如何在Oracle 11g中调试用户定义的聚合函数?,oracle,plsql,Oracle,Plsql,我试图学习如何创建用户定义的聚合函数。到目前为止,我已经能够创建一个编译良好的,但调用它会产生意外的结果。该函数是一个非常简单的测试函数,它查看设置为“Y”或“N”的许多行,如果所有行都设置为“Y”,则返回“Y”,否则返回“N”。我在一行上运行它,取而代之的是一个空白的varchar 2 我不确定调试这个的过程是什么。我尝试使用DBMS_OUTPUT.PUT_LINE(),但在数据库输出上看不到任何内容。最大的问题是它创建的函数很好,大多数代码都是对象类型。因此,如果我试图调试select语句,

我试图学习如何创建用户定义的聚合函数。到目前为止,我已经能够创建一个编译良好的,但调用它会产生意外的结果。该函数是一个非常简单的测试函数,它查看设置为“Y”或“N”的许多行,如果所有行都设置为“Y”,则返回“Y”,否则返回“N”。我在一行上运行它,取而代之的是一个空白的varchar 2

我不确定调试这个的过程是什么。我尝试使用DBMS_OUTPUT.PUT_LINE(),但在数据库输出上看不到任何内容。最大的问题是它创建的函数很好,大多数代码都是对象类型。因此,如果我试图调试select语句,它将调用已经编译的数据库上的代码

下面是函数的代码,但我不想知道为什么这样做不起作用,我想知道如何调试以便自己解决这些问题,特别是当涉及更复杂的聚合函数时

CREATE OR REPLACE TYPE MYSCHEMA.ALL_TRUE_T AS OBJECT
(
    TRUE_SO_FAR VARCHAR2(1),
    STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT ALL_TRUE_T) RETURN NUMBER,
    MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ALL_TRUE_T, value IN VARCHAR2) RETURN NUMBER,
    MEMBER FUNCTION ODCIAggregateTerminate(self IN ALL_TRUE_T, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER,
    MEMBER FUNCTION ODCIAggregateMerge(self IN OUT ALL_TRUE_T, ctx2 IN ALL_TRUE_T) RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY MYSCHEMA.ALL_TRUE_T IS
    STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT ALL_TRUE_T)
    RETURN NUMBER IS
    BEGIN
        sctx := ALL_TRUE_T('Y');
        return ODCIConst.Success;
    END;

    MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ALL_TRUE_T, value IN VARCHAR2)
    RETURN NUMBER IS
    BEGIN
        IF value <> 'Y' OR self.TRUE_SO_FAR <> 'Y' THEN
            self.TRUE_SO_FAR := 'N';
        END IF;
        RETURN ODCIConst.Success;
    END;

    MEMBER FUNCTION ODCIAggregateTerminate(self IN ALL_TRUE_T, returnValue OUT VARCHAR2, flags IN NUMBER)
    RETURN NUMBER IS
    BEGIN
        returnValue := self.TRUE_SO_FAR;
        RETURN ODCIConst.Success;
    END;

    MEMBER FUNCTION ODCIAggregateMerge(self IN OUT ALL_TRUE_T, ctx2 IN ALL_TRUE_T)
    RETURN NUMBER IS
    BEGIN
        IF ctx2.TRUE_SO_FAR = 'N' THEN
            self.TRUE_SO_FAR := 'N';
        END IF;
        RETURN ODCIConst.Success;
    END;
END;


CREATE OR REPLACE PACKAGE MYSCHEMA.ALL_TRUE_PKG IS
    FUNCTION ALL_TRUE (input VARCHAR2) RETURN VARCHAR2;
END;

CREATE OR REPLACE PACKAGE BODY MYSCHEMA.ALL_TRUE_PKG IS
    FUNCTION ALL_TRUE (input VARCHAR2) RETURN VARCHAR2
        AGGREGATE USING ALL_TRUE_T;
END;
最后,我不确定这是否相关,但我使用的是Toad11.6

编辑:

所以我试着插入一个临时日志表,但也没有成功

我添加了以下内容

MEMBER FUNCTION ODCIAggregateIterate(self IN OUT ALL_TRUE_T, value IN VARCHAR2)
RETURN NUMBER IS
BEGIN
    BEGIN
        INSERT INTO MYSCHEMA.LAWTONFOGLES_TEMP_LOG
        (
            ID,
            Message,
            Time
        )
        VALUES
        (
            'all_true',
            'test1',
            systimestamp
        );
    END;
    IF value <> 'Y' OR self.TRUE_SO_FAR <> 'Y' THEN
        self.TRUE_SO_FAR := 'N';
    END IF;
    RETURN ODCIConst.Success;
END;
CREATE OR REPLACE FUNCTION MYSCHEMA.LAWTONFOGLES_ALL_TRUE (input VARCHAR2) RETURN VARCHAR2
AGGREGATE USING ALL_TRUE_T;
然后运行这个

SELECT
    MYSCHEMA.LAWTONFOGLES_ALL_TRUE(YN)
FROM
    MYSCHEMA.YN_TEST_TABLE
并且得到了我期望的结果。代码本身似乎不是问题,但将其放入包中会导致代码中断。周四,我的Oracle DBA将向Oracle开出一张罚单,所以我一定要更新一下,为什么把它放在一个包中会破坏它,但当他们回来时,把它作为一个函数不会破坏它。在那之前,我可能不得不把它放在包裹外面


此外,我试图在它工作时添加一条put_线,但仍然没有得到输出。我认为用户定义的聚合函数的工作方式会阻止put_行工作。

如果您使用的是TOAD,请确保在运行进程之前打开DBMS_输出记录,以便可以查看输出。它应该在底部的DBMS选项卡上(如果您打开了它)。通常,您会看到一个红色圆圈,因为它默认为“关闭”。单击圆,使其为绿色


以此链接为例:

DBMS\u OUTPUT.PUT\u行应该可以工作,您可能需要使您的客户端能够查看它。在SQL*Plus上,这将是“设置服务器输出打开”,在Toad上,可能有一些按钮可以单击以启用DBMS输出。但是,正如我所解释的,您最好使用
CAST
COLLECT
而不是Oracle数据盒式磁带。有关类似的讨论和后续内容,请参阅本文。这看起来像是一个不受支持的功能,有望在未来的版本中得到解决。是的,我已经做到了。有趣的事;这是我的Oracle DBA在我联系他时给出的第一个建议。目前正在尝试插入到临时日志表中。只是为了避免明显的问题-是否将输出作为第一行。。。只是为了消除DBMS关闭的可能性。还有,对于蟾蜍,我发现自己有时需要打开或关闭它。不管出于什么原因,有时它不会启动。我添加了
begindbms\u OUTPUT.PUT\u LINE('BEGIN');结束在选择之前,我确实看到了它的输出,但没有看到任何其他输出。因此,您的调试工作正常。只是有些东西过早地停止了你的进程。您可能需要添加更多的输出,以准确地找出它停止的位置,但是,一般来说,您有一个正确的调试设置。我在自己的代码的第一行设置了一个输出,该输出将在没有结果的情况下运行。还插入了一个临时表,但没有结果。
SELECT
    MYSCHEMA.LAWTONFOGLES_ALL_TRUE(YN)
FROM
    MYSCHEMA.YN_TEST_TABLE