--现有一表如下:
CREATE TABLE DMS_WORK_CALE
(
CALE_DATE DATE NOT NULL,
CALE_SORT VARCHAR2(2 BYTE),
CALE_WTIME NUMBER(3,1)
)
--欲生成数据如下:
CALE_DATE CALE_SORT CALE_WTIME
2008-04-24 01 8
2008-04-25 01 8
2008-04-26 02 0
2008-04-27 02 0
2008-04-28 01 8
2008-04-29 01 8
2008-04-30 01 8
要求:过程传入参数( 年:如 2008),将该年下每一天按一条记录插入表。
数据规则是:
第一个字段:每天的日期
第二个字段:工作日(01)非工作日(02)
第三个字段:工作日(8)非工作日(0)
CREATE TABLE DMS_WORK_CALE
(
CALE_DATE DATE NOT NULL,
CALE_SORT VARCHAR2(2 BYTE),
CALE_WTIME NUMBER(3,1)
)
--欲生成数据如下:
CALE_DATE CALE_SORT CALE_WTIME
2008-04-24 01 8
2008-04-25 01 8
2008-04-26 02 0
2008-04-27 02 0
2008-04-28 01 8
2008-04-29 01 8
2008-04-30 01 8
要求:过程传入参数( 年:如 2008),将该年下每一天按一条记录插入表。
数据规则是:
第一个字段:每天的日期
第二个字段:工作日(01)非工作日(02)
第三个字段:工作日(8)非工作日(0)
FROM (
select to_date('2008'||'-01-01','yyyy-mm-dd')+level-1 as lv from dual
connect by level<=366)
WHERE to_char(lv,'yyyy')='2008'
;
CREATE OR REPLACE PROCEDURE crtcal(year in varchar2)
IS
i number;
td date;
tm number;
daycnt number;
tp varchar2(2);
BEGIN
if mod(to_number(year),400) = 0 or (mod(to_number(year),4) = 0 and mod(to_number(year),100) <> 0) then
daycnt := 366;
else
daycnt :=365;
end if;
td := to_date(year||'-01-01','YYYY-MM-DD');
i := 1;
tm := 0;
loop
exit when i > daycnt;
if to_char(td,'D') = 7 or to_char(td,'D') = 1 then
tm := 0;
tp := 02;
else
tp := 01;
tm := 8;
end if;
insert into doercal(DMS_WORK_CALE,CALE_SORT,CALE_WTIME) values(td,tp,tm);
td := td + 1;
i := i + 1;
end loop;
commit;
END;
CREATE OR REPLACE PROCEDURE crtcal(year in varchar2)
IS
i number;
td date;
tm number;
daycnt number;
tp varchar2(2);
BEGIN
if mod(to_number(year),400) = 0 or (mod(to_number(year),4) = 0 and mod(to_number(year),100) <> 0) then
daycnt := 366;
else
daycnt :=365;
end if;
td := to_date(year ¦ ¦'-01-01','YYYY-MM-DD');
i := 1;
tm := 0;
loop
exit when i > daycnt;
if to_char(td,'D') = 7 or to_char(td,'D') = 1 then
tm := 0;
tp := 02;
else
tp := 01;
tm := 8;
end if;
insert into DMS_WORK_CALE(CALE_DATE,CALE_SORT,CALE_WTIME) values(to_char(td,'YYYY-MM-DD'),tp,tm);
td := td + 1;
i := i + 1;
end loop;
commit;
END;
'yyyy-mm-dd') 日期,decode(to_char(to_date('2008-01-01', 'yyyy-mm-dd') + (rownum - 1),
'd'),7,'02',1,'02','01'),decode(to_char(to_date('2008-01-01', 'yyyy-mm-dd') + (rownum - 1),
'd'),7,'0',1,'0','8')
from user_objects
where rownum < 367
and to_date('2008-01-01', 'yyyy-mm-dd') + (rownum - 1) <
to_date('2009-01-01', 'yyyy-mm-dd');
create or replace procedure p_date( ad_year Varchar2 )
is
vn_days Number;
vn_date Number;
vd_date Date;
begin
For i In 1..12 Loop
Select to_number(to_char( last_day( to_date( ad_year||to_char(i,'00')||'01','yyyymmdd') ),'dd' ) ) Into vn_days From dual;
For j In 1..vn_days Loop
--2000/01/02--周日
Select to_date( ad_year||to_char(i,'00')||to_char(j,'00'),'yyyymmdd' ) Into vd_date From dual;
Select mod(Mod( ( to_date( ad_year||to_char(i,'00')||to_char(j,'00'),'yyyymmdd' ) - to_date( '20000102','yyyymmdd' ) ),7 ) + 7,7) Into vn_date From dual;
Insert Into DMS_WORK_CALE Values( vd_date,
decode( vn_date,6,'01',decode( vn_date,0,'01','02' ) ),
decode( vn_date,6,0,decode( vn_date,0,0,8 ) )
) ;
end Loop;
end Loop;
commit;
End p_date;
出来的是个序列 1,2,。366.这样可以得到366天。decode函数用法to_char(sysdate,'d')
出来的是1,2,7 这个是西方人的习惯。周7是1,周6是7.
select level lv from dual connect by level <=366;
实际上不止100
select * from (select level lv from dual connect by level <=366)
366行。
为什么会出现这个问题不知道
theday date;
YearDays Pls_integer;
Type t_s is table of pls_integer;
v_s t_s:=t_s();
begin
theday:=to_date('2008-01-01','yyyy-mm-dd')-1;
YearDays:=to_date('2008-12-31','yyyy-mm-dd')-theday;
for i in 1.. yearDays loop
v_s.extend;
v_s(i):=i;
end loop;
forall i in 1..yearDays
Insert into testDay values(theday+v_s(i),decode(to_char(theday+v_s(i),'d'),6,'02',7,'02','01'),
decode(to_char(theday+v_s(i),'d'),6,'0',7,'0','8')
);
commit;
end;大概是这个意思,看你如何定义哪天是工作日,此外注意nls设置。 我的例子是定义6,7为休息日.
改成:values(td,tp,tm);
就可以了。
我本地的表用的是varchar2所以做了一个转换。
在sql文中使用connect by 循环,
plsql中的直接使用循环 日期增加的方法可以直接加1,也没有必要按照12个月来循环。
然后就是那点:判断是不是闰年。
decode的写法:decode(mod(to_number(:year),400),0,366,decode(mod(to_number(:year),100),0,365,decode(mod(to_number(:year),4),0,366,365)))
或者先判断
create or replace procedure p_date( ad_year Varchar2 )
is
vn_num Number;
vn_days Number;
vn_date Number;
vd_date Date;
begin
Select Count(*) Into vn_num From DMS_WORK_CALE Where cale_date = to_date(ad_year||'-01-01','yyyy-mm-dd');
If vn_num > 0 Then
Delete From DMS_WORK_CALE Where to_char( cale_date,'yyyy' ) = ad_year;
End If;
For i In 1..12 Loop
Select to_number(to_char( last_day( to_date( ad_year||to_char(i,'00')||'01','yyyymmdd') ),'dd' ) ) Into vn_days From dual;
For j In 1..vn_days Loop
--2000/01/02--周日
Select to_date( ad_year||to_char(i,'00')||to_char(j,'00'),'yyyymmdd' ) Into vd_date From dual;
Select mod(Mod( ( to_date( ad_year||to_char(i,'00')||to_char(j,'00'),'yyyymmdd' ) - to_date( '20000102','yyyymmdd' ) ),7 ) + 7,7) Into vn_date From dual;
Insert Into DMS_WORK_CALE Values( vd_date,
decode( vn_date,6,'01',decode( vn_date,0,'01','02' ) ),
decode( vn_date,6,0,decode( vn_date,0,0,8 ) )
) ;
end Loop;
end Loop;
commit;
End p_date;
还望不吝赐教。
因为pl/sql引擎把sql内容传输给sql引擎是需要耗费资源的。
真正执行sql的是sql引擎,而pl/sql引擎仅仅是预处理Pl/sql,最终代码需要再交付给sql引擎。