打包过程调用私有函数--在SQL中无法使用。

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

我有一个包,里面有两个私有函数和一个调用它们的过程。这两个函数向存储过程返回承诺付款的到期日期(第一次和最后一次)。存储过程返回这些日期,以及捐赠者的名字和ID。

CREATE OR REPLACE PACKAGE PLEDGE_PKG IS
 PROCEDURE DD_PLIST_PP
    (p_id IN DD_PLEDGE.IDPLEDGE%TYPE,
     p_first DD_DONOR.FIRSTNAME%TYPE,
     p_last DD_DONOR.LASTNAME%TYPE,
     p_payfirst OUT DATE,
     p_paylast OUT DATE);
END;
CREATE OR REPLACE PACKAGE BODY PLEDGE_PKG IS
-- Determines 1st Payment Due Date based on ID.
 FUNCTION dd_paydate1_pf
  (p_id IN dd_pledge.idpledge%TYPE)
  RETURN DATE
  IS
  lv_pl_dat DATE;
  lv_mth_txt VARCHAR2(2);
  lv_yr_txt VARCHAR2(4);
 BEGIN
  SELECT ADD_MONTHS(pledgedate,1)
    INTO lv_pl_dat
    FROM dd_pledge
    WHERE idpledge = p_id;
  lv_mth_txt := TO_CHAR(lv_pl_dat,'mm');
  lv_yr_txt := TO_CHAR(lv_pl_dat,'yyyy');
  RETURN TO_DATE((lv_mth_txt || '-01-' || lv_yr_txt),'mm-dd-yyyy');
 END dd_paydate1_pf;

-- Determines LAST Payment Due Date based on ID.
 FUNCTION dd_payend_pf
  (p_id IN dd_pledge.idpledge%TYPE)
  RETURN DATE
  IS
  lv_pay1_dat DATE;
  lv_mths_num dd_pledge.paymonths%TYPE;
 BEGIN
  SELECT dd_paydate1_pf(idpledge), paymonths - 1                        -- LINE 28
    INTO lv_pay1_dat, lv_mths_num
    FROM dd_pledge
    WHERE idpledge = p_id;
  IF lv_mths_num = 0 THEN
     RETURN lv_pay1_dat;
  ELSE
     RETURN ADD_MONTHS(lv_pay1_dat, lv_mths_num);
  END IF;
 END dd_payend_pf;

-- Displays Donor Name, ID, First, Last payment using Donor ID
 PROCEDURE DD_PLIST_PP
    (p_id IN DD_PLEDGE.IDPLEDGE%TYPE,
     p_first DD_DONOR.FIRSTNAME%TYPE,
     p_last DD_DONOR.LASTNAME%TYPE,
     p_payfirst OUT DATE,
     p_paylast OUT DATE)
 AS
    lv_first DD_DONOR.FIRSTNAME%TYPE;
    lv_last DD_DONOR.LASTNAME%TYPE;
 BEGIN
    SELECT FIRSTNAME, LASTNAME
     INTO lv_first, lv_last
     FROM DD_DONOR
     WHERE p_id = IDDONOR;

    p_payfirst := PLEDGE_PKG.DD_PAYDATE1_PF(p_id);
    p_paylast := PLEDGE_PKG.DD_PAYEND_PF(p_id);
 END DD_PLIST_PP;

END;

我得到的错误来自于第二个块。

LINE/COL ERROR
-------- -----------------------------------------------------------------
28/3     PL/SQL: SQL Statement ignored
28/10    PL/SQL: ORA-00904: : invalid identifier
28/10    PLS-00231: function 'DD_PAYDATE1_PF' may not be used in SQL

:)我的问题是,我想调用PLEDGE_PKG.DD_PLIST_PP,然后返回名字,和两个日期。希望这个解释能帮到你,谢谢你的帮助。

oracle plsql
2个回答
2
投票

按照你的标记,第28行是

SELECT dd_paydate1_pf(idpledge), paymonths - 1

这条语句是SQL,你在包内(就是PLSQL)使用它。SQL引擎不能访问该包的私有功能,除非你把它公开。因此,什么 工作是

  • 你在第55行使用的是什么?

    p_payfirst := PLEDGE_PKG.DD_PAYDATE1_PF(p_id);
    

    这里所有的东西都在PLSQL中(虽然,这是有问题的,因为你在第28行中从另一个表中传递P_ID参数的值),或者是

  • 在包的规范中声明该函数是公开的。

[编辑]

根据你的评论(文字太多,无法通过其他评论回复)。

它是关于 语境切换. select dd_paydate1_pf ... 是SQL从PLSQL中调用的。SQL试图选择函数的结果,在SQL层找不到该函数。如果你在前面加上包名,即 select pledge_pkg.dd_paydate1_pf...,还是不行,因为该函数没有在包中声明。规格 但对包装来说是私有的 身体.

你可以做的是重写函数为。

FUNCTION dd_payend_pf
  (p_id IN dd_pledge.idpledge%TYPE)
  RETURN DATE
  IS
  lv_pay1_dat DATE;
  lv_mths_num dd_pledge.paymonths%TYPE;
 BEGIN
  lv_pay1_dat := dd_paydate1_pf(p_id);  --> move it out of SELECT

  SELECT paymonths - 1
    INTO lv_mths_num
    FROM dd_pledge
    WHERE idpledge = p_id;

  IF lv_mths_num = 0 THEN
     RETURN lv_pay1_dat;
  ELSE
     RETURN ADD_MONTHS(lv_pay1_dat, lv_mths_num);
  END IF;
 END dd_payend_pf;

看看是否有用


0
投票

不能把私有函数作为sql查询的一部分。 由于我的第一个答案没有解决这个问题,所以我很晚才加上这个答案,现在看到这里有一个很好的答案。 但只是为了提供信息,希望对DATE的使用有所帮助,这里有一个有趣的包,使用了一个私有函数(简单地返回你发工资的那一个月的哪一天)和一个公共函数,返回你的下一个发工资日。

create or replace package date_test is
    -- public:
    function pay_day return date;
end;
/

create or replace package body date_test is
    -- private function:
    function paid_on return number is
    begin
        return 24;
    end;

    -- public:
    function pay_day return date is
        -- use private function:
        v_paydate_DD number := paid_on;
        v_next_payday date;
    begin
        v_next_payday := trunc(sysdate,'MONTH') + v_paydate_DD - 1;
        if trunc(sysdate) >= trunc(v_next_payday)  then
          select add_months(v_next_payday,1) into v_next_payday from dual;
        end if;
        return v_next_payday;
    end;
end;
/


select date_test.pay_day from dual;
© www.soinside.com 2019 - 2024. All rights reserved.