2

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

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

编辑2:

所以,为了让事情变得更有趣,当它不在包中时,它可以工作。

我做了以下

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 工作。

4

1 回答 1

1

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

以这个链接为例: http: //geekbrigade.wordpress.com/2009/04/09/how-to-set-and-view-dbms-output-of-oralce-in-toad/

于 2013-08-13T18:19:20.323 回答