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
    循环的输入;但是你可以在那里使用光标,就像我在下面所说的那样
  • i
    表示星期六或星期日时,在循环中选择未找到数据的select(在本例中是第4个,假设您在二月运行它)
  • 为每一行获取所有非周末行的计数是低效的,尽管对于如此少量的数据来说这并不重要
  • 您指的是日期(“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.