我创建了自己的 Oracle 类型和聚合函数:
作为单独的函数,该函数创建为:
create or replace FUNCTION MY_AGGR_FN (input NUMBER) RETURN NUMBER
PARALLEL_ENABLE AGGREGATE USING MY_AGGR_TYPE;
效果很好!现在我想将此函数放入 pwn 包中,但我不知道如何从中创建包体。
这是我的包裹声明:
create or replace PACKAGE MY_PKG AS
FUNCTION MY_AGGR_FN(n NUMBER) RETURN NUMBER;
END MY_PKG;
但是在包体中我不能只放:
create or replace PACKAGE BODY MY_PKG AS
FUNCTION MY_AGGR_FN(n NUMBER) RETURN NUMBER
PARALLEL_ENABLE AGGREGATE USING MY_AGGR_TYPE;
END MY_PKG;
您不能在包的公共签名中定义聚合函数,因为语法不允许。
CREATE FUNCTION
文档给出了独立函数的语法如下:
create_function ::=
plsql_function_source ::=
CREATE PACKAGE
文档给出了包函数的语法如下:
package_function_declaration ::=
虽然独立函数可以在其签名中包含
AGGREGATE
子句,但包函数签名不允许该选项。
所以:
CREATE TYPE FirstAggregationType AS OBJECT(
value NUMBER,
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT FirstAggregationType
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT FirstAggregationType,
value IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT FirstAggregationType,
returnValue OUT NUMBER,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT FirstAggregationType,
ctx IN OUT FirstAggregationType
) RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY FirstAggregationType
IS
STATIC FUNCTION ODCIAggregateInitialize(
ctx IN OUT FirstAggregationType
) RETURN NUMBER
IS
BEGIN
ctx := FirstAggregationType( NULL );
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateIterate(
self IN OUT FirstAggregationType,
value IN NUMBER
) RETURN NUMBER
IS
BEGIN
IF self.value IS NULL THEN
self.value := value;
END IF;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateTerminate(
self IN OUT FirstAggregationType,
returnValue OUT NUMBER,
flags IN NUMBER
) RETURN NUMBER
IS
BEGIN
returnValue := self.value;
RETURN ODCIConst.SUCCESS;
END;
MEMBER FUNCTION ODCIAggregateMerge(
self IN OUT FirstAggregationType,
ctx IN OUT FirstAggregationType
) RETURN NUMBER
IS
BEGIN
self.value := COALESCE( self.value, ctx.value );
RETURN ODCIConst.SUCCESS;
END;
END;
/
CREATE PACKAGE tools IS
FUNCTION FIRST( value NUMBER )
RETURN NUMBER PARALLEL_ENABLE;
END tools;
/
CREATE PACKAGE BODY tools IS
FUNCTION FIRST( value NUMBER )
RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING FirstAggregationType;
END tools;
/
将编译,但如果你尝试使用它:
CREATE TABLE table_name ( id, group_id, value ) AS
SELECT 1, 13, NULL FROM DUAL UNION ALL
SELECT 2, 13, 1 FROM DUAL UNION ALL
SELECT 3, 13, 2 FROM DUAL UNION ALL
SELECT 4, 28, 1 FROM DUAL UNION ALL
SELECT 5, 28, NULL FROM DUAL UNION ALL
SELECT 6, 28, 4 FROM DUAL;
SELECT group_id,
Tools.First( value ) AS first_value
FROM table_name
GROUP BY group_id;
你得到了例外:
ORA-00979: not a GROUP BY expression
如果您尝试修改包签名以添加
AGGREGATE
子句:
CREATE OR REPLACE PACKAGE tools IS
FUNCTION FIRST( value NUMBER )
RETURN NUMBER PARALLEL_ENABLE AGGREGATE;
END tools;
/
然后你会得到异常:
PLS-00220: simple name required in this context