创建oracle函数的问题
Issue in creating oracle function
我创建了一个需要输入月份 (11) 和年份 (2018) 的函数,它将 return 下个月的第一个星期日。
Create or replace function get_effectivedate (par_Month in int,Par_Year in int);
Return date
Is
startDate varchar;
edate date;
begin
startDate := par_Month+Par_Year;
edate := select next_day(add_months(trunc(startDate, 'MM'), 1), 'Sunday') as EffectiveDate from dual;
return edate;
end;
这个函数在 运行 时提示我,它在编译时抛出一些错误。
错误:
LINE/COL ERROR
--------- -------------------------------------------------------------
7/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: := . ( @ % ; not null range with default character The symbol ";" was substituted for "BEGIN" to continue.
9/14 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification> <an alternat
11/2 PLS-00103: Encountered the symbol "RETURN"
Errors: check compiler log
Function GET_EFFECTIVEDATE compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
7/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: := . ( @ % ; not null range with default character The symbol ";" was substituted for "BEGIN" to continue.
9/14 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification> <an alternat
11/2 PLS-00103: Encountered the symbol "RETURN"
Errors: check compiler log
Function GET_EFFECTIVEDATE compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
7/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: := . ( @ % ; not null range with default character The symbol ";" was substituted for "BEGIN" to continue.
9/14 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification> <an alternat
11/2 PLS-00103: Encountered the symbol "RETURN"
Errors: check compiler log
你想调用 startDate 变量,所以删除 & 符号,
&
是一个符号 for prompting user's input。将您的代码行更改为:
edate := select next_day(add_months(trunc(startDate, 'MM'), 1), 'Sunday') as EffectiveDate from dual;
&value is a user entered parameter
您有几个问题:
- 你在
create ...
行有一个尾随分号;
- 您正在使用替换变量(由
&
表示)- 系统会提示您这样做;
- 您使用
int
而不是 number
作为参数类型(不是真正的错误,但通常使用本机类型更好);
- 你的
startdate
局部变量被声明为 varchar
而不是 varchar2
,这有效但不鼓励,但无论哪种方式你都必须为字符串指定最大长度(即startdate varchar2(6);
);
- 您将这两个数字与
+
相加,并将其结果(即 2029)放入字符串变量;
- 您正在使用该字符串变量 - 如果您忽略
&
- 作为数字而不是日期,那么 trunc
将不起作用;
- 如果你已经过了这个月的第一天,那么
trunc
就毫无意义了。
你可以很简单地做到这一点:
create or replace function get_effectivedate (par_month in number, par_year in number)
return date
is
begin
return next_day(
add_months(
-- converts the two number to a single string, and then converts that to a date
to_date(to_char(par_year, 'FM0000') || to_char(par_month, 'FM00'), 'YYYYMM'),
1),
'Sunday');
end;
/
然后将其命名为:
select get_effectivedate(11, 2018) from dual;
GET_EFFECT
----------
2018-12-02
或今年所有月份通过 CTE:
with cte (year, month) as (
select 2018, level from dual connect by level <= 12
)
select year, month, get_effectivedate(month, year)
from cte;
YEAR MONTH GET_EFFECT
---------- ---------- ----------
2018 1 2018-02-04
2018 2 2018-03-04
2018 3 2018-04-08
2018 4 2018-05-06
2018 5 2018-06-03
2018 6 2018-07-08
2018 7 2018-08-05
2018 8 2018-09-02
2018 9 2018-10-07
2018 10 2018-11-04
2018 11 2018-12-02
2018 12 2019-01-06
将两个参数显式转换为字符串可以让您控制前导零,因此您可以确定传入 1 和 234 将转换为字符串 '01'
和 '0234'
,因此当它们连接起来形成 '023401'
,以匹配格式模型。
如果您没有明确指定天数,那么 to_date()
会为您提供该月的第一天。
如果一个月的第一天本身就是星期天,上面的函数会得到第二个星期日,你在评论中说这是你真正想要的。 (通知2018-07-08)。如果您确实只想要第一个星期日而不需要进一步调整,您可以:
return next_day(
add_months(
-- converts the two numbers to a single string, and then converts that to a date
to_date(to_char(par_year, 'FM0000') || to_char(par_month, 'FM00'), 'YYYYMM'),
1) - 1, -- find first day of next month, then go back one day to last day of this month
'Sunday'); -- find next Sunday from that day
或更简单地说:
return next_day(
last_day(
-- converts the two numbers to a single string, and then converts that to a date
to_date(to_char(par_year, 'FM0000') || to_char(par_month, 'FM00'), 'YYYYMM')
), -- find last day of this month
'Sunday'); -- find next Sunday from that day
两者都给出L
YEAR MONTH GET_EFFECT
---------- ---------- ----------
2018 1 2018-02-04
2018 2 2018-03-04
2018 3 2018-04-01
2018 4 2018-05-06
2018 5 2018-06-03
2018 6 2018-07-01
2018 7 2018-08-05
2018 8 2018-09-02
2018 9 2018-10-07
2018 10 2018-11-04
2018 11 2018-12-02
2018 12 2019-01-06
我创建了一个需要输入月份 (11) 和年份 (2018) 的函数,它将 return 下个月的第一个星期日。
Create or replace function get_effectivedate (par_Month in int,Par_Year in int);
Return date
Is
startDate varchar;
edate date;
begin
startDate := par_Month+Par_Year;
edate := select next_day(add_months(trunc(startDate, 'MM'), 1), 'Sunday') as EffectiveDate from dual;
return edate;
end;
这个函数在 运行 时提示我,它在编译时抛出一些错误。
错误:
LINE/COL ERROR
--------- -------------------------------------------------------------
7/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: := . ( @ % ; not null range with default character The symbol ";" was substituted for "BEGIN" to continue.
9/14 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification> <an alternat
11/2 PLS-00103: Encountered the symbol "RETURN"
Errors: check compiler log
Function GET_EFFECTIVEDATE compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
7/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: := . ( @ % ; not null range with default character The symbol ";" was substituted for "BEGIN" to continue.
9/14 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification> <an alternat
11/2 PLS-00103: Encountered the symbol "RETURN"
Errors: check compiler log
Function GET_EFFECTIVEDATE compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
7/1 PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: := . ( @ % ; not null range with default character The symbol ";" was substituted for "BEGIN" to continue.
9/14 PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set specification> <an alternat
11/2 PLS-00103: Encountered the symbol "RETURN"
Errors: check compiler log
你想调用 startDate 变量,所以删除 & 符号,
&
是一个符号 for prompting user's input。将您的代码行更改为:
edate := select next_day(add_months(trunc(startDate, 'MM'), 1), 'Sunday') as EffectiveDate from dual;
&value is a user entered parameter
您有几个问题:
- 你在
create ...
行有一个尾随分号; - 您正在使用替换变量(由
&
表示)- 系统会提示您这样做; - 您使用
int
而不是number
作为参数类型(不是真正的错误,但通常使用本机类型更好); - 你的
startdate
局部变量被声明为varchar
而不是varchar2
,这有效但不鼓励,但无论哪种方式你都必须为字符串指定最大长度(即startdate varchar2(6);
); - 您将这两个数字与
+
相加,并将其结果(即 2029)放入字符串变量; - 您正在使用该字符串变量 - 如果您忽略
&
- 作为数字而不是日期,那么trunc
将不起作用; - 如果你已经过了这个月的第一天,那么
trunc
就毫无意义了。
你可以很简单地做到这一点:
create or replace function get_effectivedate (par_month in number, par_year in number)
return date
is
begin
return next_day(
add_months(
-- converts the two number to a single string, and then converts that to a date
to_date(to_char(par_year, 'FM0000') || to_char(par_month, 'FM00'), 'YYYYMM'),
1),
'Sunday');
end;
/
然后将其命名为:
select get_effectivedate(11, 2018) from dual;
GET_EFFECT
----------
2018-12-02
或今年所有月份通过 CTE:
with cte (year, month) as (
select 2018, level from dual connect by level <= 12
)
select year, month, get_effectivedate(month, year)
from cte;
YEAR MONTH GET_EFFECT
---------- ---------- ----------
2018 1 2018-02-04
2018 2 2018-03-04
2018 3 2018-04-08
2018 4 2018-05-06
2018 5 2018-06-03
2018 6 2018-07-08
2018 7 2018-08-05
2018 8 2018-09-02
2018 9 2018-10-07
2018 10 2018-11-04
2018 11 2018-12-02
2018 12 2019-01-06
将两个参数显式转换为字符串可以让您控制前导零,因此您可以确定传入 1 和 234 将转换为字符串 '01'
和 '0234'
,因此当它们连接起来形成 '023401'
,以匹配格式模型。
如果您没有明确指定天数,那么 to_date()
会为您提供该月的第一天。
如果一个月的第一天本身就是星期天,上面的函数会得到第二个星期日,你在评论中说这是你真正想要的。 (通知2018-07-08)。如果您确实只想要第一个星期日而不需要进一步调整,您可以:
return next_day(
add_months(
-- converts the two numbers to a single string, and then converts that to a date
to_date(to_char(par_year, 'FM0000') || to_char(par_month, 'FM00'), 'YYYYMM'),
1) - 1, -- find first day of next month, then go back one day to last day of this month
'Sunday'); -- find next Sunday from that day
或更简单地说:
return next_day(
last_day(
-- converts the two numbers to a single string, and then converts that to a date
to_date(to_char(par_year, 'FM0000') || to_char(par_month, 'FM00'), 'YYYYMM')
), -- find last day of this month
'Sunday'); -- find next Sunday from that day
两者都给出L
YEAR MONTH GET_EFFECT
---------- ---------- ----------
2018 1 2018-02-04
2018 2 2018-03-04
2018 3 2018-04-01
2018 4 2018-05-06
2018 5 2018-06-03
2018 6 2018-07-01
2018 7 2018-08-05
2018 8 2018-09-02
2018 9 2018-10-07
2018 10 2018-11-04
2018 11 2018-12-02
2018 12 2019-01-06