Oracle自带的聚合函数在包中

问题描述 投票:0回答:1

我创建了自己的 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;
sql oracle plsql
1个回答
0
投票

您不能在包的公共签名中定义聚合函数,因为语法不允许。


CREATE FUNCTION
文档给出了独立函数的语法如下:

create_function ::=

Syntax diagram for CREATE FUNCTION

plsql_function_source ::=

Syntax diagram for CREATE FUNCTION source

CREATE PACKAGE
文档给出了包函数的语法如下:

package_function_declaration ::=

Syntax diagram for a CREATE 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

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.