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