我有一个包,里面有两个私有函数和一个调用它们的过程。这两个函数向存储过程返回承诺付款的到期日期(第一次和最后一次)。存储过程返回这些日期,以及捐赠者的名字和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,然后返回名字,和两个日期。希望这个解释能帮到你,谢谢你的帮助。
按照你的标记,第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;
看看是否有用
不能把私有函数作为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;