Sql 调用返回带有日期的表的函数
我有一个函数的问题。 我需要一张表,上面有一个月的日期、一天的名称以及该月的工作日数量。 我已经在这里找到了一些帮助,并根据需要对其进行了修改,但我无法运行/编译该函数 以下是我到目前为止的情况:Sql 调用返回带有日期的表的函数,sql,oracle,function,date,Sql,Oracle,Function,Date,我有一个函数的问题。 我需要一张表,上面有一个月的日期、一天的名称以及该月的工作日数量。 我已经在这里找到了一些帮助,并根据需要对其进行了修改,但我无法运行/编译该函数 以下是我到目前为止的情况: create or replace TYPE DATE_ROW AS OBJECT ( MyDate DATE, Dayname VARCHAR2(12), Amount Integer ) create or replace TYPE DATE_TABLE as table of D
create or replace TYPE DATE_ROW AS OBJECT
(
MyDate DATE,
Dayname VARCHAR2(12),
Amount Integer
)
create or replace TYPE DATE_TABLE as table of DATE_ROW
create or replace FUNCTION myfinaldays (mydate date)
RETURN DATE_TABLE
PIPELINED
IS
V_MYDATE DATE;
V_DAYNAME VARCHAR2(12);
V_AMOUNT NUMBER;
BEGIN
with this_month as (
select trunc(to_date('mydate'), 'mm')+level-1 dy
from dual
connect by level < (trunc(add_months(to_date('mydate'),1), 'mm')- trunc(to_date('mydate'), 'mm'))+1
)
FOR i IN 0 .. (select count(*) from this_month) LOOP
select (dy) Daydate,
to_char(dy, 'day'), Dayname,
( select count(*)
from this_month
where to_char(dy, 'dy') not in ('sat', 'sun')
) Amount
from this_month
where to_char(dy, 'dy') not in ('sat', 'sun')
and EXTRACT(day from to_date(dy)) = i;
pipe row (date_row(v_mydate,v_dayname, v_amount));
END LOOP;
RETURN;
END;
我只能给出一个日期作为参数
我希望有人能在这里帮助我,因为这正慢慢让我发疯。
任何想法、例子或想法都将不胜感激
更新:
好的,这是mybe的更新。关于我的问题,请提供更多帮助信息:
这是可行的,我的目标是把它放在一个函数中,这样我就可以用1个参数调用它:
with this_month as (
select trunc(to_date('01.02.12'), 'mm')+level-1 dy
from dual
connect by level < (trunc(add_months(to_date('01.02.12'),1), 'mm')- trunc(to_date('01.02.12'), 'mm'))+1
)
select (dy) mydate, (select count(*) from this_month) Days_in_month
, to_char(dy, 'day') Dayname
, ( select count(*) from this_month where to_char(dy, 'dy') not in ('sat', 'sun') ) Amount
from this_month
where to_char(dy, 'dy') not in ('sat', 'sun') ;
由于我的Oracle不运行英语,因此错误已被翻译,因此我希望能够正确猜测。由于您的函数是表值函数(返回表),因此不能将其作为常规函数调用。 你必须加入它: 在Oracle中类似这样的内容:
select * from date_table t
cross join table( myfinaldays(<t.date colum>))
从日期表t中选择*
交叉联接表(myfinaldays())
这里有很多问题
- 您不能在
中直接为i in 1..x使用
选择
(它应该是1,而不是0),您必须选择一个局部变量并将其用作结束值
- 不能将
一起用作与
循环的输入;但是你可以在那里使用光标,就像我在下面所说的那样for
- 当
表示星期六或星期日时,在循环中选择未找到数据的select(在本例中是第4个,假设您在二月运行它)i
- 为每一行获取所有非周末行的计数是低效的,尽管对于如此少量的数据来说这并不重要
- 您指的是日期(“mydate”);mydate已经是一个日期,“mydate”是一个与之无关的字符串
to_char(x,'dy')
不会到处返回sat
或sun
,但我会假设这将以受限的方式使用,所以您不会太在意
通过尝试找出您期望的输出,我认为这会起作用(修改类型以获得您添加到原始问题中的days\u in\u month
):
date\u表
是一种类型;这不应该是select*from table(myfinaldays(截止日期('01.02.12','DD.MM.RR'))
?(当然是猜测日期格式,但更希望看到显式转换).@Alex Poole第一个问题是函数本身无法编译..我无法修复它。但是谢谢你的建议,我想这可能是我遇到的下一个问题。你编译函数或调用函数时遇到错误了吗?不管怎样,你都会遇到什么错误?我不认为你可以使用带有子句的“input”而不是o对于这样的循环,您混合了SQL和PL/SQL。您可能需要构建一个PL/SQL表来保存生成的日期。但是对于初学者,to_date('mydate'))
;mydate
已经是一个日期,'mydate'
是一个与之无关的字符串……哇,非常感谢。是的,就是这样。我想我将对该代码进行一次特殊检查,以便了解它在每一步中所做的操作。不过,还有一件事:现在我应该可以像处理其他表一样处理此表了对吗?如“从表中选择mydate(myfinaldays(截止日期('01.02.12','DD.MM.RR'))”,其中mydate不在表中(从holidaycalendar中选择日期)“或者使用左join、union等等……我必须测试什么最有效。只需猜一下这一步的语法,但我相信您理解我的意思。好的,让它可以处理我需要的所有内容……再次感谢您的帮助。@Thevagabond-没问题。您可以将其视为一个表,但我会有点担心将另一个表中的字段作为<代码>mydate
参数。要排除假日日期,您可能需要在函数中执行此操作,这样就不必在其他地方重复此操作。如果您尚未执行此操作,请参阅[常见问题解答],了解如何确认有用的答案。
- Error(15,5): PL/SQL: ORA-00928: Keyword SELECT missing
- Error(22,8): PLS-00113: END-Definer 'LOOP' must complete 'myfinaldays' in row 1, comlumn 10
- Error(23,4): PLS-00103: Found the symbol "RETURN"
select * from date_table t
cross join table( myfinaldays(<t.date colum>))
create or replace type date_row as object
(
mydate DATE,
dayname VARCHAR2(12),
days_in_month NUMBER,
amount NUMBER
)
/
create or replace type date_table as table of date_row
/
create or replace function myfinaldays (mydate date)
return date_table pipelined deterministic is
begin
for r in (
select *
from (
select dy as daydate,
to_char(dy, 'day') as dayname,
count(*) over () as days_in_month,
sum(case when to_char(dy, 'dy') in ('sat', 'sun')
then 0 else 1 end) over () as amount
from (
select trunc(mydate, 'mm')+level-1 dy
from dual
connect by level < (trunc(add_months(mydate, 1), 'mm')
- trunc(mydate, 'mm')) + 1
)
)
where to_char(daydate, 'dy') not in ('sat', 'sun')
) loop
pipe row (date_row(r.daydate, r.dayname, r.days_in_month, r.amount));
end loop;
end myfinaldays;
/
alter session set nls_date_format = 'DD.MM.RR';
select * from table(myfinaldays(to_date('01.02.12', 'DD.MM.RR')));
MYDATE DAYNAME DAYS_IN_MONTH AMOUNT
-------- ------------ ------------- ----------
01.02.12 wednesday 29 21
02.02.12 thursday 29 21
03.02.12 friday 29 21
06.02.12 monday 29 21
...
29.02.12 wednesday 29 21
21 rows selected.