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

时间:2013-08-13 17:23:04

标签: oracle plsql

我正在尝试学习如何创建用户定义的聚合函数。到目前为止,我已经能够创建一个编译良好的编程,但调用它会产生意想不到的结果。该函数是一个非常简单的测试函数,可以查看设置为“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;

以下是我的称呼方式。 YN_TEST_TABLE目前有一行,其中包含'N'。

SELECT
    MYSCHEMA.ALL_TRUE_PKG.ALL_TRUE(YN)
FROM
    MYSCHEMA.YN_TEST_TABLE

最后,我不确定这是否相关,但我使用的是Toad 11.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;

临时日志中没有任何内容,但也没有错误消息。就好像四个聚合函数部分都没有被调用一样。

EDIT2:

因此,为了使事情变得更有趣,当它不在包中时,它就可以工作。

我做了以下

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_line,但仍然没有得到输出。我认为用户定义聚合函数的方式可以阻止put_line工作。

1 个答案:

答案 0 :(得分:1)

如果您使用的是TOAD,请务必在运行proc之前打开DBMS_OUTPUT录音,这样您就可以看到输出。它应该在底部的DBMS选项卡上(如果你打开它)。通常情况下,您会看到一个红色圆圈,因为它默认为关闭。单击圆圈使其变为绿色。

请参阅此链接作为示例:http://geekbrigade.wordpress.com/2009/04/09/how-to-set-and-view-dbms-output-of-oralce-in-toad/