학과테이블입니다. (학과 코드와 이름입니다.)
create table major (
major_num varchar2(10) --학과번호
constraint maj_maj_num_pk primary key,
major_name varchar2(20) not null --학과이름
);
학생테이블입니다.(학생의 정보입니다.)
create table student (
stu_num number(15) --학번
constraint stu_stu_num_pk primary key,
passwd number(15) not null, --주민번호
year number(3), --학년
major_num varchar2(10) --학과번호
constraint stu_maj_num_fk references major(major_num),
name varchar2(15), --이름
address varchar2(30), --주소
phone_num varchar2(15), --전화번호
e_mail varchar2(40), --이메일주소
total_grade number(3) default 21, --신청가능학점
cur_grade number(3) default 0 --현재신청학점
);
교수테이블입니다. (교수의 정보입니다.)
create table prof (
prof_num number(15) --교수번호
constraint prof_prof_num_pk primary key,
passwd number(15) not null, --주민번호
major_num varchar2(10) --학과번호
constraint prof_prof_num_fk references major(major_num),
name varchar2(15), --이름
address varchar2(30), --주소
phone_num varchar2(15), --전화번호
e_mail varchar2(40) --이메일주소
);
과목테이블입니다. (과목의 정보입니다.)
(그래서 많은 분들은 제의도와는 다르게 학번과 과목을 pk로 잡으라하시더군요.
그러면, 한사람밖에 삽입되지 않나요? 과목도 다른 사람이 먼저 신청하면,
신청을 할 수 없는 거구요...)
create table subject (
sub_num varchar2(10) primary key, --과목번호
sub_name varchar2(15) not null, --과목명
sub_part number(3) , --영역
time1 varchar2(5), --월요일
time2 varchar2(5), --화요일
time3 varchar2(5), --수요일
time4 varchar2(5), --목요일
time5 varchar2(5), --금요일
full_student number(3) not null, --총인원
current_student number(3) default 0, --현수강신청인원
room_num varchar2(5), --강의실번호
part_num varchar2(5) not null, --분반
part varchar2(10), --과목분류(전선)
grade number(3), --학점
prof_num number(15) --교수번호
constraint sub_prof_num_fk references prof(prof_num),
major_num varchar2(10) --소속학과
constraint sub_maj_num_fk references major(major_num)
);
수강신청테이블입니다. (여기엔 수강신청을 하는 모든 학생의 과목내용이 기록됩니다.)
create table ord (
stu_num number(15) not null, --학번
sub_num varchar2(10) not null, --과목명
time1 varchar2(5), --월요일
time2 varchar2(5), --화요일
time3 varchar2(5), --수요일
time4 varchar2(5), --목요일
time5 varchar2(5), --금요일
ord_date date default sysdate, --신청일
constraint ord_stu_num_fk foreign key (stu_num)
references student(stu_num),
constraint ord_sub_num_fk foreign key (sub_num)
references subject(sub_num)
);
==그리고 스크립트 처리 부분입니다. 좀 지저분하지만 아니, 많이 지저분하지만
이해해 주세요 ^^==
create or replace procedure ins_sub(
the_stu_num in number default null ,
the_passwd in number default null,
the_sub_num in varchar2 default null)
is
v_sub_rec subject%rowtype;
v_ord_rec ord%rowtype;
v_time1 subject.time1%type;
v_time2 subject.time2%type;
v_time3 subject.time3%type;
v_time4 subject.time4%type;
v_time5 subject.time5%type;
v_full_student subject.full_student%type;
v_current_student subject.current_student%type;
v_name student.name%type;
v_major_name major.major_name%type;
v_sub_part subject.sub_part%type;
time_value boolean default false;
cursor cu is select * from ord
where stu_num = the_stu_num
order by sub_num;
dummy BOOLEAN;
begin
select name into v_name
from student
where stu_num = the_stu_num;
select * into v_sub_rec from subject where sub_num = the_sub_num;
select time1, time2, time3, time4, time5
into v_time1, v_time2, v_time3, v_time4, v_time5
from subject
where sub_num = the_sub_num;
htp.htmlopen;
htp.headopen;
htp.title('1단계 수강신청');
htp.headclose;
htp.bodyopen;
htp.p('<BODY background="/ows-img/orhmbkgn.jpg" text="#000088" link="#BB0000" vl
ink="#BB0000">');
htp.centeropen;
=*=*=*=*=*이부분입니다. 이부분을 어떻게 해결해야 될까요?
제 의도는 기존의 수강신청테이블에 시간표가 중복되는지의 여부를 체크한다고
작성해본 부분입니다.
/*
for i in cu loop
if ( ((substr(i.time1,1,1) <> v_time1) or (substr(i.time1,-1,1) <> v_time1) or
(substr(i.time1,1,3) <> v_time1))
and ((substr(i.time2,1,1) <> v_time2) or (substr(i.time2,-1,1) <> v_time2) or
(substr(i.time2,1,3) <> v_time2))
and ((substr(i.time3,1,1) <> v_time3) or (substr(i.time3,-1,1) <> v_time3) or
(substr(i.time3,1,3) <> v_time3))
and ((substr(i.time4,1,1) <> v_time4) or (substr(i.time4,-1,1) <> v_time4) or
(substr(i.time4,1,3) <> v_time4))
and ((substr(i.time5,1,1) <> v_time5) or (substr(i.time5,-1,1) <> v_time5) or
(substr(i.time5,1,3) <> v_time5)))
then
v_var := 100;
time_value := TRUE;
end if;
end loop;
*/
htp.header(1,'환 영 합 니 다.');
htp.p(v_name||' 학생이 신청한 과목 '||the_sub_num||' 입니다');
htp.br;
if(time_value) then
select full_student, current_student into v_full_student, v_current_student
from subject
where sub_num = the_sub_num;
if ( v_current_student <= v_full_student ) then
--같은 과목이 검출되는지 여부를 조사하는 코드 첨가해야한다.
v_current_student := v_current_student + 1;
update subject
set current_student = v_current_student
where sub_num = the_sub_num;
htp.br;
htp.br;
insert into ord(stu_num, sub_num, time1, time2, time3, time4, time5)
values (the_stu_num, the_sub_num, v_sub_rec.time1, v_sub_rec.time2,
v_sub_rec.time3, v_sub_rec.time4, v_sub_rec.time5);
htp.p('성공적으로 신청되었습니다.');
else
htp.bold('지금 신청하신 과목은 정원을 초과합니다. 다시 신청해 주십시오.');
end if;
end if;
dummy := owa_util.tableprint('ord,subject','BORDER',owa_util.html_table,
'ord.sub_num,subject.part,subject.sub_name, ord.ord_date ',
'where ord.sub_num = subject.sub_num and
ord.stu_num = '''||the_stu_num||''' ',
'과목번호,구분,과목명,신청일');
htp.br;
htp.br;
htp.br;
htp.br;
--
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.br;
-- htp.formopen( 'state1' );
-- htp.formsubmit(null,'과목보기 창으로');
htp.br;
htp.br;
--
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.bold('취소할 과목이 있으면 아래 사항을 정확히 기입하시오');
htp.br;
htp.formopen( 'login_check3' );
htp.tableData( '<FONT color=blue size=3>' ||
htf.bold( '당신의 학번은, ') ||
'</FONT>' || htf.formtext('the_stu_num',15,15) ||
'<FONT color=blue size=3>' ||
htf.bold( ' ') ||
'</FONT>');
htp.tableData( '<FONT color=blue size=3>' ||
htf.bold( '당신의 주민번호는, ') ||
'</FONT>' || htf.formpassword('the_passwd',15,15) ||
'<FONT color=blue size=3>' ||
htf.bold( ' ') ||
'</FONT>');
htp.tableData( '<FONT color=blue size=3>' ||
htf.bold( '과목번호 ') ||
'</FONT>' || htf.formtext('the_sub_num',15,15) ||
'<FONT color=blue size=3>' ||
htf.bold( '를 ') ||
'</FONT>');
htp.formsubmit(null,'삭제합니다');
--
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.br;
htp.br;
htp.br;
htp.formopen( 'state1' );
htp.formsubmit(null,'과목보기 창으로');
htp.formclose;
htp.br;
htp.br;
htp.br;
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.bodyclose;
htp.htmlclose;
exception
when no_data_found then
htp.centeropen;
htp.p('좀만 더 힘 써봐, 화이팅!!!');
when others then
htp.centeropen;
htp.p(the_sub_num||'과목의 시간이 중복되었습니다.');
htp.bold('다시 신청해 주십시오!!!');
htp.br;
htp.br;
htp.formopen('state1');
htp.formsubmit(null,'과목보기 창으로');
end;
/
show err
답변
제가생각할때는 설계를 바꾸는게 최선입니다.
현재설계가 RDB에 적합한 설계라고는 볼수 없습니다.
하지만 지금 table의 layout을 유지하고
중복되는 시간을 check하려면 방법이 없는것은 아닙니다.
다만,부적합한 설계로 인하여 구현이 어려워진다는게 문제지요..
procedure 안에서 cursor를 쓰지말고
다음 query를 이용해 보세요.
parameter는 the_sub_num,the_stu_num 을 사용합니다.
query에서 return되는 값이 0보다 크면 중복되는 시간이 이미
ord table 에 있는 겁니다.
return 값이 0이라면 더이상의 check없이 insert 하시면 됩니다.
SELECT COUNT(*)
FROM (SELECT DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5) ATIME
FROM (select 'A'||SUBSTRB(TIME1,NO,1) T1,
'B'||SUBSTRB(TIME2,NO,1) T2,
'C'||SUBSTRB(TIME3,NO,1) T3,
'D'||SUBSTRB(TIME4,NO,1) T4,
'E'||SUBSTRB(TIME5,NO,1) T5
from subject,(SELECT ROWNUM NO FROM USER_TABLES WHERE ROWNUM <= 5)
where sub_num = the_sub_num),
(SELECT ROWNUM RNO FROM USER_TABLES WHERE ROWNUM <= 5)
WHERE LENGTHB(DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5)) > 1
INTERSECT
SELECT DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5) ATIME
FROM (select 'A'||SUBSTRB(TIME1,NO,1) T1,
'B'||SUBSTRB(TIME2,NO,1) T2,
'C'||SUBSTRB(TIME3,NO,1) T3,
'D'||SUBSTRB(TIME4,NO,1) T4,
'E'||SUBSTRB(TIME5,NO,1) T5
from ORD,(SELECT ROWNUM NO FROM USER_TABLES WHERE ROWNUM <= 5)
where sTu_num = the_stu_num),
(SELECT ROWNUM RNO FROM USER_TABLES WHERE ROWNUM <= 5)
WHERE LENGTHB(DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5)) > 1
)
create table major (
major_num varchar2(10) --학과번호
constraint maj_maj_num_pk primary key,
major_name varchar2(20) not null --학과이름
);
학생테이블입니다.(학생의 정보입니다.)
create table student (
stu_num number(15) --학번
constraint stu_stu_num_pk primary key,
passwd number(15) not null, --주민번호
year number(3), --학년
major_num varchar2(10) --학과번호
constraint stu_maj_num_fk references major(major_num),
name varchar2(15), --이름
address varchar2(30), --주소
phone_num varchar2(15), --전화번호
e_mail varchar2(40), --이메일주소
total_grade number(3) default 21, --신청가능학점
cur_grade number(3) default 0 --현재신청학점
);
교수테이블입니다. (교수의 정보입니다.)
create table prof (
prof_num number(15) --교수번호
constraint prof_prof_num_pk primary key,
passwd number(15) not null, --주민번호
major_num varchar2(10) --학과번호
constraint prof_prof_num_fk references major(major_num),
name varchar2(15), --이름
address varchar2(30), --주소
phone_num varchar2(15), --전화번호
e_mail varchar2(40) --이메일주소
);
과목테이블입니다. (과목의 정보입니다.)
(그래서 많은 분들은 제의도와는 다르게 학번과 과목을 pk로 잡으라하시더군요.
그러면, 한사람밖에 삽입되지 않나요? 과목도 다른 사람이 먼저 신청하면,
신청을 할 수 없는 거구요...)
create table subject (
sub_num varchar2(10) primary key, --과목번호
sub_name varchar2(15) not null, --과목명
sub_part number(3) , --영역
time1 varchar2(5), --월요일
time2 varchar2(5), --화요일
time3 varchar2(5), --수요일
time4 varchar2(5), --목요일
time5 varchar2(5), --금요일
full_student number(3) not null, --총인원
current_student number(3) default 0, --현수강신청인원
room_num varchar2(5), --강의실번호
part_num varchar2(5) not null, --분반
part varchar2(10), --과목분류(전선)
grade number(3), --학점
prof_num number(15) --교수번호
constraint sub_prof_num_fk references prof(prof_num),
major_num varchar2(10) --소속학과
constraint sub_maj_num_fk references major(major_num)
);
수강신청테이블입니다. (여기엔 수강신청을 하는 모든 학생의 과목내용이 기록됩니다.)
create table ord (
stu_num number(15) not null, --학번
sub_num varchar2(10) not null, --과목명
time1 varchar2(5), --월요일
time2 varchar2(5), --화요일
time3 varchar2(5), --수요일
time4 varchar2(5), --목요일
time5 varchar2(5), --금요일
ord_date date default sysdate, --신청일
constraint ord_stu_num_fk foreign key (stu_num)
references student(stu_num),
constraint ord_sub_num_fk foreign key (sub_num)
references subject(sub_num)
);
==그리고 스크립트 처리 부분입니다. 좀 지저분하지만 아니, 많이 지저분하지만
이해해 주세요 ^^==
create or replace procedure ins_sub(
the_stu_num in number default null ,
the_passwd in number default null,
the_sub_num in varchar2 default null)
is
v_sub_rec subject%rowtype;
v_ord_rec ord%rowtype;
v_time1 subject.time1%type;
v_time2 subject.time2%type;
v_time3 subject.time3%type;
v_time4 subject.time4%type;
v_time5 subject.time5%type;
v_full_student subject.full_student%type;
v_current_student subject.current_student%type;
v_name student.name%type;
v_major_name major.major_name%type;
v_sub_part subject.sub_part%type;
time_value boolean default false;
cursor cu is select * from ord
where stu_num = the_stu_num
order by sub_num;
dummy BOOLEAN;
begin
select name into v_name
from student
where stu_num = the_stu_num;
select * into v_sub_rec from subject where sub_num = the_sub_num;
select time1, time2, time3, time4, time5
into v_time1, v_time2, v_time3, v_time4, v_time5
from subject
where sub_num = the_sub_num;
htp.htmlopen;
htp.headopen;
htp.title('1단계 수강신청');
htp.headclose;
htp.bodyopen;
htp.p('<BODY background="/ows-img/orhmbkgn.jpg" text="#000088" link="#BB0000" vl
ink="#BB0000">');
htp.centeropen;
=*=*=*=*=*이부분입니다. 이부분을 어떻게 해결해야 될까요?
제 의도는 기존의 수강신청테이블에 시간표가 중복되는지의 여부를 체크한다고
작성해본 부분입니다.
/*
for i in cu loop
if ( ((substr(i.time1,1,1) <> v_time1) or (substr(i.time1,-1,1) <> v_time1) or
(substr(i.time1,1,3) <> v_time1))
and ((substr(i.time2,1,1) <> v_time2) or (substr(i.time2,-1,1) <> v_time2) or
(substr(i.time2,1,3) <> v_time2))
and ((substr(i.time3,1,1) <> v_time3) or (substr(i.time3,-1,1) <> v_time3) or
(substr(i.time3,1,3) <> v_time3))
and ((substr(i.time4,1,1) <> v_time4) or (substr(i.time4,-1,1) <> v_time4) or
(substr(i.time4,1,3) <> v_time4))
and ((substr(i.time5,1,1) <> v_time5) or (substr(i.time5,-1,1) <> v_time5) or
(substr(i.time5,1,3) <> v_time5)))
then
v_var := 100;
time_value := TRUE;
end if;
end loop;
*/
htp.header(1,'환 영 합 니 다.');
htp.p(v_name||' 학생이 신청한 과목 '||the_sub_num||' 입니다');
htp.br;
if(time_value) then
select full_student, current_student into v_full_student, v_current_student
from subject
where sub_num = the_sub_num;
if ( v_current_student <= v_full_student ) then
--같은 과목이 검출되는지 여부를 조사하는 코드 첨가해야한다.
v_current_student := v_current_student + 1;
update subject
set current_student = v_current_student
where sub_num = the_sub_num;
htp.br;
htp.br;
insert into ord(stu_num, sub_num, time1, time2, time3, time4, time5)
values (the_stu_num, the_sub_num, v_sub_rec.time1, v_sub_rec.time2,
v_sub_rec.time3, v_sub_rec.time4, v_sub_rec.time5);
htp.p('성공적으로 신청되었습니다.');
else
htp.bold('지금 신청하신 과목은 정원을 초과합니다. 다시 신청해 주십시오.');
end if;
end if;
dummy := owa_util.tableprint('ord,subject','BORDER',owa_util.html_table,
'ord.sub_num,subject.part,subject.sub_name, ord.ord_date ',
'where ord.sub_num = subject.sub_num and
ord.stu_num = '''||the_stu_num||''' ',
'과목번호,구분,과목명,신청일');
htp.br;
htp.br;
htp.br;
htp.br;
--
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.br;
-- htp.formopen( 'state1' );
-- htp.formsubmit(null,'과목보기 창으로');
htp.br;
htp.br;
--
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.bold('취소할 과목이 있으면 아래 사항을 정확히 기입하시오');
htp.br;
htp.formopen( 'login_check3' );
htp.tableData( '<FONT color=blue size=3>' ||
htf.bold( '당신의 학번은, ') ||
'</FONT>' || htf.formtext('the_stu_num',15,15) ||
'<FONT color=blue size=3>' ||
htf.bold( ' ') ||
'</FONT>');
htp.tableData( '<FONT color=blue size=3>' ||
htf.bold( '당신의 주민번호는, ') ||
'</FONT>' || htf.formpassword('the_passwd',15,15) ||
'<FONT color=blue size=3>' ||
htf.bold( ' ') ||
'</FONT>');
htp.tableData( '<FONT color=blue size=3>' ||
htf.bold( '과목번호 ') ||
'</FONT>' || htf.formtext('the_sub_num',15,15) ||
'<FONT color=blue size=3>' ||
htf.bold( '를 ') ||
'</FONT>');
htp.formsubmit(null,'삭제합니다');
--
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.br;
htp.br;
htp.br;
htp.formopen( 'state1' );
htp.formsubmit(null,'과목보기 창으로');
htp.formclose;
htp.br;
htp.br;
htp.br;
htp.p('<TD><HR NOSHADE size="2"></TD>');
htp.bodyclose;
htp.htmlclose;
exception
when no_data_found then
htp.centeropen;
htp.p('좀만 더 힘 써봐, 화이팅!!!');
when others then
htp.centeropen;
htp.p(the_sub_num||'과목의 시간이 중복되었습니다.');
htp.bold('다시 신청해 주십시오!!!');
htp.br;
htp.br;
htp.formopen('state1');
htp.formsubmit(null,'과목보기 창으로');
end;
/
show err
답변
제가생각할때는 설계를 바꾸는게 최선입니다.
현재설계가 RDB에 적합한 설계라고는 볼수 없습니다.
하지만 지금 table의 layout을 유지하고
중복되는 시간을 check하려면 방법이 없는것은 아닙니다.
다만,부적합한 설계로 인하여 구현이 어려워진다는게 문제지요..
procedure 안에서 cursor를 쓰지말고
다음 query를 이용해 보세요.
parameter는 the_sub_num,the_stu_num 을 사용합니다.
query에서 return되는 값이 0보다 크면 중복되는 시간이 이미
ord table 에 있는 겁니다.
return 값이 0이라면 더이상의 check없이 insert 하시면 됩니다.
SELECT COUNT(*)
FROM (SELECT DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5) ATIME
FROM (select 'A'||SUBSTRB(TIME1,NO,1) T1,
'B'||SUBSTRB(TIME2,NO,1) T2,
'C'||SUBSTRB(TIME3,NO,1) T3,
'D'||SUBSTRB(TIME4,NO,1) T4,
'E'||SUBSTRB(TIME5,NO,1) T5
from subject,(SELECT ROWNUM NO FROM USER_TABLES WHERE ROWNUM <= 5)
where sub_num = the_sub_num),
(SELECT ROWNUM RNO FROM USER_TABLES WHERE ROWNUM <= 5)
WHERE LENGTHB(DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5)) > 1
INTERSECT
SELECT DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5) ATIME
FROM (select 'A'||SUBSTRB(TIME1,NO,1) T1,
'B'||SUBSTRB(TIME2,NO,1) T2,
'C'||SUBSTRB(TIME3,NO,1) T3,
'D'||SUBSTRB(TIME4,NO,1) T4,
'E'||SUBSTRB(TIME5,NO,1) T5
from ORD,(SELECT ROWNUM NO FROM USER_TABLES WHERE ROWNUM <= 5)
where sTu_num = the_stu_num),
(SELECT ROWNUM RNO FROM USER_TABLES WHERE ROWNUM <= 5)
WHERE LENGTHB(DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5)) > 1
)
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
26 | DYNAMIC SQL 이란? (퍼온글 : 출처모름) | 운영자 | 2002.09.17 | 3291 |
25 | PL/SQL에서 ARRAY사용 예제 | 운영자 | 2002.09.17 | 3254 |
24 | 년중 몇번째 주간인지 알아내기(FUNCTION) - ORACLE이 제공하는 것과 다름 | 운영자 | 2002.09.17 | 3733 |
23 | SORT후 번호부여 | 운영자 | 2002.09.17 | 2774 |
22 | JOIN 과 UNION 의 선후관계 | 운영자 | 2002.09.17 | 4634 |
» | 중복 DATA CHECK | 운영자 | 2002.09.17 | 2790 |
20 | crontab 에 오라클 환경변수를 인식시킬때 [1] | 원우석 | 2004.12.06 | 5025 |
19 | oracle proc 에서 stdarg.h파일사용하기위한 환경설정 | 원우석 | 2004.12.06 | 12829 |
18 | 시스템카탈로그에서 프로시져 정보확인 쿼리 | 원우석 | 2004.07.31 | 2976 |
17 | 프로시져생성 문을 실행하는 방법 | 원우석 | 2004.07.31 | 2721 |
16 | 시스템카탈로그에서 테이블 정보확인 쿼리 | 원우석 | 2004.07.31 | 4559 |
15 | DB2 에러 메시지 확인 | 원우석 | 2004.07.31 | 3044 |
14 | 필드 타입케스팅 | 원우석 | 2004.07.31 | 2973 |
13 | 암호화(이름과,암호를 암호화할때) | 원우석 | 2004.07.31 | 2758 |
12 | 결과를 n개 행만을 취할때 | 원우석 | 2004.07.31 | 2561 |
11 | pre컴파일 및 실행계획로그만들기 | 원우석 | 2004.07.31 | 2752 |
10 | CLP 명령모음집 | 원우석 | 2004.07.31 | 2876 |
9 | sql 문 실행명령 | 원우석 | 2004.07.31 | 3567 |
8 | DB2 종료후 다시 시작 | 원우석 | 2004.07.31 | 2936 |
7 | lock 상태 확인 | 원우석 | 2004.07.31 | 4909 |