0

私はデータを含む休日のテーブルを持っています

    HOLIDAYDA DESCRIPTION
   --------- --------------------
   19-JAN-11 to
   17-JAN-11 to
   10-JAN-11 new day

今、私は週の最初の営業日が欲しいです。IE:「2011年1月12日」を入力として渡す場合、2011年1月10日は休日であるため、最初の営業日として2011年1月11日としてo/pが必要です。

これが私のコードです:

create or replace procedure sample as
   l_dStartDay date;
   l_dHolidayDate date;
begin

    select trunc(to_date(sysdate),'Day') 
      into l_dStartday 
      from dual;

 dbms_output.put_line('first day of the week ');
 dbms_output.put_line(l_dStartDay);

 for i in 2..5 Loop
   select holidaydate 
     from holiday 
     into l_dHolidayDate 
    where holidaydate = (l_dStartDay + i);

  if(l_dHolidaydate is null) then
    dbms_output.put_line(l_dStartDay+i);
  end if;
exit;
end loop;
end;

上記のプログラムをコンパイルしましたが、「コンパイルエラーで作成されたプロシージャ」を使用しました。

新しく追加された:コンパイルエラー:

 LINE/COL ERROR
 -------- -----------------------------------------------------------------
 9/1      PL/SQL: SQL Statement ignored
 9/33     PL/SQL: ORA-00933: SQL command not properly ended

エラー

BEGIN sample; END;
      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object SYSTEM.SAMPLE is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

エラーの理由を教えてもらえますか?可能であれば解決策を教えてください。

4

3 に答える 3

8

「私は上記のプログラムをコンパイルしましたが、 Procedure created with compilation errors

TOADやSQLDeveloperなどのIDEを使用している場合は、コンパイルエラーが自動的に表示されます。それ以外の場合は、次のコマンドを使用してSQL*Plusでアクセスできます。

SQL>    show errors

クエリできるUSER_ERRORSなどのビューもあります。

INTO句は射影の直後に続く必要があるため、問題はおそらくSELECTステートメントです。

   select holidaydate 
     into l_dHolidayDate 
     from holiday 
    where holidaydate = l_dStartDay + i);

気をつけてください、これも間違っているように見えます:

select trunc(to_date(sysdate),'Day') 

SYSDATEはすでにDATEですが、Oracleの最近のバージョンでは、DATE列でTO_DATEを使用することをより許容する傾向があります。日付から時間要素を切り捨てる場合、これがデフォルトの動作であるため、フォーマットマスクを含める必要はありません。

trunc(some_date_variable)

(たとえば)月の最初の日が必要な場合にのみ、マスクを含める必要があります。

trunc(some_date_variable, 'MON')

週の最初の日を見つけたい場合は、次のようにします。

SQL> select
  2      trunc(to_date('01-DEC-2010', 'DD-MON-YYYY'), 'D') start_of_wk
  3  from dual
  4  /

START_OF_
---------
29-NOV-10

SQL>

週の最初の日は地域の設定によって異なることに注意してください。一部の地域では、週の最初の日が稼働日(たとえば、英国では月曜日)であり、そうでない地域(米国では日曜日は1日目)です。したがって、オフセットを追加する必要がある場合があります。


コンパイルエラーを解決すると、おそらく未処理のNO_DATA_FOUND例外に関連するsoemランタイムエラーが見つかります。これは、一致するレコードが見つからない場合、ルックアップクエリがNULLを返さないため、失敗します。

これは簡単な手順です。SQLは物事を行うための最も効率的な方法であるため、SQLソリューションを使用します。内部クエリは、CONNECT BYトリックを使用して、日付の結果セットを生成します。次に、これはMINUS set演算子によって削減され、その週の範囲内のすべての休日が除外されます。最後に、外部クエリはクエリから最も早い日付を返します。

create or replace procedure get_first_working_day 
    ( p_tgt_date in date )
is
    l_st_day date := trunc(p_tgt_date, 'D');
    l_working_day date := trunc(p_tgt_date, 'D');
begin
    dbms_output.put_line('first day of week = '||l_st_day);

    select min(day_of_wk)
    into l_working_day
    from ( select l_st_day + (level-1) as day_of_wk
           from dual
           connect by level <= 5
           minus
           select holidaydate
           from hols
           where holidaydate between l_st_day and l_st_day + 4 );

    dbms_output.put_line('first working day of week = '||l_working_day
                        ||'::'|| to_char(l_working_day, 'DAY'));

end get_first_working_day;
/

このテストデータ(英国の銀行の休日のビザンチン状態を反映している)を考えると...

SQL> select holidate from hols
  2  order by 1
  3  /

HOLIDAYDA
---------
25-DEC-10
26-DEC-10
27-DEC-10
28-DEC-10
01-JAN-11
03-JAN-11

6 rows selected.

SQL>

...実際の手順は次のとおりです。

SQL> set serveroutput on size unlimited
SQL>
SQL> exec get_first_working_day (sysdate)
first day of week = 10-JAN-11
first working day of week = 10-JAN-11::MONDAY

PL/SQL procedure successfully completed.

SQL>
SQL> exec get_first_working_day (to_date( '04-JAN-2011', 'DD-MON-YYYY'))
first day of week = 03-JAN-11
first working day of week = 04-JAN-11::TUESDAY

PL/SQL procedure successfully completed.

SQL>
SQL> exec get_first_working_day (to_date( '01-JAN-2011', 'DD-MON-YYYY'))
first day of week = 27-DEC-10
first working day of week = 29-DEC-10::WEDNESDAY

PL/SQL procedure successfully completed.

SQL>

ちなみに、これは非常に悪い習慣です。

PLS-00905: object SYSTEM.SAMPLE is invalid

組み込みのSYSまたはSYSTEMアカウントを自分の作業に使用しないでください。何かを壊す可能性が高すぎます。代わりに、新しいユーザーアカウントを作成してください。

于 2011-01-11T06:22:44.233 に答える
0

私はその線を推測しています

where holidaydate = l_dStartDay + i);

本来あるべきではない場所があるので間違ってい)ます。

于 2011-01-11T06:17:12.993 に答える
0

すでに述べたエラーは別として、このループは一定の回数繰り返されるため、「EXIT」句を削除してみてください。また、次のようにブロックを終了するときにブロック名を指定してみてください。

    LOOP    
    ...
    END LOOP;
END ObjectName;

ObjectNameはトップレベルのプログラムです。ここでは、「サンプル」になるため、次のようになります。

    LOOP
    ...
    END LOOP;
END sample;
于 2011-01-18T19:51:46.563 に答える