상세 컨텐츠

본문 제목

[오라클] 4월 21일 예제

카테고리 없음

by esoesmio 2023. 4. 21. 17:09

본문

-- PL/SQL
-- 세팅
;
SET SERVEROUTPUT ON;

-- 데이터 타입 확인
DESC STUDENT;

-- 6. 레코드
-- 테이블 생성


ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ
    스튜던트_레코드라는 테이블을 만든다. 스토던트를 참조해서;


CREATE TABLE STUDENT_RECORD
AS
SELECT *
FROM STUDENT;

-- 레코드 생성

ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ STU_REC라는 레코드를 만드는데 거기에 들어가는 요소들의 타입이랑 의미를 정의
    그리고 STU_REC레코드를 인스턴스화.STUDENTREC 이름으로
    거기에 각각 요소를 인서트함
    그걸 위에만든 테이블인 student_record 테이블 에 넣음


    ;
DECLARE
    --레코드 선언부
    TYPE STU_REC IS RECORD
                    (
                        --데이터가 저장될 테이블의 칼럼의 순서와 타입을 모두 동일하게 맞춰아한다.


                        SNO   VARCHAR2(8) NOT NULL := '11012',

--notnull로 정의된 변수는 초기치를 할당하여야 합니다.

--                         SNO   VARCHAR2(8) NOT NULL,
                        SNAME STUDENT.SNAME%TYPE,
                        SEX   STUDENT.SEX%TYPE,
                        SYEAR NUMBER(1, 0) DEFAULT 1,
                        MAJOR STUDENT.MAJOR%TYPE,
                        AVR   STUDENT.AVR%TYPE
                    );

    STUDENTREC STU_REC;
BEGIN
    STUDENTREC.SNO := '11011';
    STUDENTREC.SNAME := '문동주';
    STUDENTREC.SEX := '여';
    STUDENTREC.MAJOR := '컴공';
    STUDENTREC.AVR := 2.5;

    DBMS_OUTPUT.PUT_LINE(STUDENTREC.SNO);
    DBMS_OUTPUT.PUT_LINE(STUDENTREC.SNAME);
    DBMS_OUTPUT.PUT_LINE(STUDENTREC.SEX);
    DBMS_OUTPUT.PUT_LINE(STUDENTREC.MAJOR);
    DBMS_OUTPUT.PUT_LINE(STUDENTREC.SYEAR);
    DBMS_OUTPUT.PUT_LINE(STUDENTREC.AVR);

    INSERT INTO STUDENT_RECORD VALUES STUDENTREC;
END;
/


CREATE TABLE STUDENT_RECORD2
AS
SELECT *
FROM STUDENT;


-- 저장된 데이터 확인
SELECT *
FROM STUDENT_RECORD
WHERE SNO = '11012';

데이터수정;
;;
    --레코드 선언부
--;;
//////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
    //////////////////////////////////////
11012 이건 뭐냐?
        ;;--
        ------
        ;

ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ STU_REC라는 레코드를 만드는데 거기에 들어가는 요소들의 타입이랑 의미를 정의
    그리고 STU_REC레코드를 인스턴스화.STUDENTREC 이름으로
    거기에 각각 요소를 인서트함(넣기 위해 준비해줌)
update student_record
set
    row = studentrec
    or
          major = studentrec.major,
    avr = studentrec.avr,
    syear = studentrec.syear
where sno = '11011';
이런형식으로
insert 말고 업데이트 형식으로 바꿔줌.;;;;
;
DECLARE
    TYPE STU_REC IS RECORD
                    (
                        --데이터가 저장될 테이블의 칼럼의 순서와 타입을 모두 동일하게 맞춰아한다.


                        SNO   VARCHAR2(8) NOT NULL := '11012',
                        SNAME STUDENT.SNAME%TYPE,
                        SEX   STUDENT.SEX%TYPE,
                        SYEAR NUMBER(1, 0) DEFAULT 1,
                        MAJOR STUDENT.MAJOR%TYPE,
                        AVR   STUDENT.AVR%TYPE
                    );

    STUDENTREC STU_REC;
BEGIN
    STUDENTREC.SNO := '11011';
    STUDENTREC.SNAME := '문동주';
    STUDENTREC.SEX := '여';
    STUDENTREC.MAJOR := '생물';
    STUDENTREC.AVR := 3.5;
    studentrec.SYEAR := 3;

    --데이터수정

    update student_record
    set
        row = studentrec


        --or

--     major = studentrec.major,
--     avr = studentrec.avr,
--     syear = studentrec.syear
    where sno = '11011';

END;
/



SELECT *
FROM STUDENT_RECORD
WHERE SNO = '11011';


-- //;;;;;;;;;;;;;;;;;;;;;;
-- 이너레코드 만들기;;;;;;;;;;;;;;;;;;;;;;
-- ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ    stu_rec 안에 stu_rec가 있는 구조;;
-- score_rec타입 정의하고 stu_rec타입 정의하고
-- begin
--     select
--     into 식으로 집어넣는다
--         아마 중첩으로 정의하면 그냥 바로 값을 넣을 수 있나보다
--         출력해낼때는는 a.b.score 이런식으로 해야되니ㅏ보다
--
--
--             ;;/
declare
    type score_rec is record
                      (

                          cno    score.cno%type,
                          sno    score.sno%type,
                          result score.result%type

                      );

    type stu_rec is record
                    (

                        SNO      VARCHAR2(8) NOT NULL := '11012',
                        SNAME    STUDENT.SNAME%TYPE,
                        SEX      STUDENT.SEX%TYPE,
                        SYEAR    NUMBER(1, 0) DEFAULT 1,
                        -- 널이 들어와도 1로 잡힘


                        MAJOR    STUDENT.MAJOR%TYPE,
                        AVR      STUDENT.AVR%TYPE,

                        scorerec score_rec


                    );

    studentrec stu_rec;
begin
    select st.sno,
           st.sname,
           st.sex,
           st.syear,
           st.major,
           st.avr,
           sc.cno,
           sc.sno,
           sc.result
           -------------------------------아 인투는 뭘 의미하는가
           -------------------------------아 인투는 뭘 의미하는가
           -------------------------------아 인투는 뭘 의미하는가
           -------------------------------아 인투는 뭘 의미하는가
           --- 아마 그 테이블에 집어 넣는다는걸 의미하는듯.

    into studentrec.sno, studentrec.sname , studentrec.sex, studentrec.SYEAR, studentrec.MAJOR, studentrec.avr, studentrec.scorerec.cno, studentrec.scorerec.sno, studentrec.scorerec.result
    from student st
             join score sc on st.SNO = sc.sno
    where st.SNO = '915601'
      and sc.cno = '2368';

    dbms_output.PUT_LINE(studentrec.sno);
    dbms_output.PUT_LINE(studentrec.sname);
    dbms_output.PUT_LINE(studentrec.syear);
    dbms_output.PUT_LINE(studentrec.major);
    dbms_output.PUT_LINE(studentrec.avr);
    dbms_output.PUT_LINE(studentrec.scorerec.result);

end;
/

declare
    geg number := 4;
begin
    dbms_output.PUT_LINE(geg);

end;
/
--     연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열ㅍ 연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열연관배열ㅍ
--
--
--
-- 동일한 데이터 타입의 데이터들을 모아놓은 자료형;
--     배열을 만드는데 numarr(1) = 이런 배열을 만들어라. 루프를만들어서;;
declare
    type number_array is table of number
        index by pls_integer;
    num    number := 0;
    numarr number_array;


begin
    loop
        num := num + 1;
        numarr(num) := num;
        exit when num > 5;

    end loop;

    DBMS_OUTPUT.PUT_LINE(numarr(1));
    DBMS_OUTPUT.PUT_LINE(numarr(2));
    DBMS_OUTPUT.PUT_LINE(numarr(3));
    DBMS_OUTPUT.PUT_LINE(numarr(4));
    DBMS_OUTPUT.PUT_LINE(numarr(5));

end;
/
--     레코드와 배열을 조합하여 레코드타입의 배열 생성(자바의 객체 배열과 비슷);
--     stu_rec의 요소 타입들 정ㅇ의해놓고
--     %%이건 그냥 출력만 하는거%%%
--     stu_rec의 배열 student_array이다.
--     루프를 넣는다.
--     루프에서 1에서 10까지 돌려서 넣음;
declare
    type stu_rec is record
                    (

                        SNO   VARCHAR2(8) NOT NULL := '11012',
                        SNAME STUDENT.SNAME%TYPE,
                        SEX   STUDENT.SEX%TYPE,
                        SYEAR NUMBER(1, 0) DEFAULT 1,
                        MAJOR STUDENT.MAJOR%TYPE,
                        AVR   STUDENT.AVR%TYPE

                    );

    --레코드 타입의 배열 선언
    type student_array is table of stu_rec
        index by pls_integer;
    stuarr student_array;
    idx    number := 1;
begin
    loop
        stuarr(idx).sno := 10000 + idx;
        stuarr(idx).SNAME := 'A';
        stuarr(idx).SYEAR := mod(idx, 4) + 1;
        stuarr(idx).MAJOR := '컴공';
        DBMS_OUTPUT.PUT_LINE(stuarr(idx).sno);
        DBMS_OUTPUT.PUT_LINE(stuarr(idx).sname);
        DBMS_OUTPUT.PUT_LINE(stuarr(idx).syear);
        DBMS_OUTPUT.PUT_LINE(stuarr(idx).major);
        idx := idx + 1;
        exit when idx > 10;


    end loop;


end;
/
--     /;;
--         ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ /////////////////////////////////
--         레코드 하나를 정의해서
--
--     배열 안에 넣은거;;;
--     레코드와 배열을 조합하여 레코드타입의 배열 생성(자바의 객체 배열과 비슷);
--     stu_rec의 요소 타입들 정ㅇ의해놓고
--     stu_rec의 배열 student_array이다.
--     루프를 넣는다.
--     루프에서 1에서 10까지 돌려서 넣음
--
--
--     이걸 출력하지 않고 student_record에 넣는다.;

declare
    type stu_rec is record
                    (

                        SNO   VARCHAR2(8) NOT NULL := '11012',
                        SNAME STUDENT.SNAME%TYPE,
                        SEX   STUDENT.SEX%TYPE,
                        SYEAR NUMBER(1, 0) DEFAULT 1,
                        MAJOR STUDENT.MAJOR%TYPE,
                        AVR   STUDENT.AVR%TYPE

                    );

    --레코드 타입의 배열 선언
    type student_array is table of stu_rec
        index by pls_integer;
    stuarr student_array;
    idx    number := 1;
begin
    loop
        stuarr(idx).sno := 10000 + idx;
        stuarr(idx).SNAME := 'A';
        stuarr(idx).SYEAR := mod(idx, 4) + 1;
        stuarr(idx).MAJOR := '컴공';


        insert into student_record
        values stuarr(idx);


        idx := idx + 1;
        exit when idx > 10;


    end loop;


end;
/;
select *
from STUDENT_RECORD
where sno like '1000%';


--rowtype을 이용해서 연관배열 생성
--     ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ 아예 student에서 타입들을 rowtype로 가져와서
--     로우배열을 만들엇 넣는것.
--     스튜던트의 로우타입을 갖고와서 하는거. 처음에 정의를 할 필요가 전혀 없음;;
declare
    type stu_array is table of student%rowtype
        index by pls_integer;
    idx    number := 1;
    stuarr stu_array;
begin
    loop
        stuarr(idx).sno := 20000 + idx;
        stuarr(idx).sname := 'B' || idx;
        stuarr(idx).MAJOR := '소프트웨어';
        stuarr(idx).syear := mod(idx, 4) + 1;

        insert into STUDENT_RECORD
        values stuarr(idx);
        idx := idx + 1;
        exit when idx > 10;
    end loop;
end;
/

select *
from student_record
where sno like '2000%';


declare
    -- exist함수는 true/false를 리턴하기 때문에 출력하는 매개변수로 사용불가
    --if 나 case조건절에 사용한다.
    --dbms_output.put_line(stuarr.exists(1))
    type stu_array is table of student%rowtype
        index by pls_integer;
    stuarr stu_array;
begin

    stuarr(1).sno := 20000 + 1;
    stuarr(1).sname := 'B' || 1;
    stuarr(1).MAJOR := '소프트웨어';
    stuarr(1).syear := 1;

    stuarr(2).sno := 20000 + 2;
    stuarr(2).sname := 'B' || 2;
    stuarr(2).MAJOR := '소프트웨어';
    stuarr(2).syear := 2;

    stuarr(3).sno := 20000 + 3;
    stuarr(3).sname := 'B' || 3;
    stuarr(3).MAJOR := '소프트웨어';
    stuarr(3).syear := 3;

    stuarr(10).sno := 20000 + 10;
    stuarr(10).sname := 'B' || 10;
    stuarr(10).MAJOR := '소프트웨어';
    stuarr(10).syear := 4;

--     DBMS_OUTPUT.PUT_LINE(stuarr.EXISTS(4));
    DBMS_OUTPUT.PUT_LINE(stuarr.count);
    --     DBMS_OUTPUT.PUT_LINE(stuarr.first);
--     DBMS_OUTPUT.PUT_LINE(stuarr.last);
    DBMS_OUTPUT.PUT_LINE(stuarr.prior(10));
    DBMS_OUTPUT.PUT_LINE(stuarr.next(10));

    stuarr.DELETE(3);


    DBMS_OUTPUT.PUT_LINE(stuarr.count);


    if stuarr.EXISTS(3) then
        DBMS_OUTPUT.PUT_LINE('3번 인덱스 있음');
    else
        DBMS_OUTPUT.PUT_LINE('3번 인덱스 없음');

    end if;


end;
/


--아까 했던 into도 커서의 한 종류라고 볼 수 있음 명시적으로 커서를 사용하지는 않았찌만

--     1 - 8 커서
--     한 행만 조사하는 커서;;;;;;;;;;;;;;
--쿼리의 결과를 저장하는 쿼리
declare
    --커서선언

    -- sno가 915301인 student 정보 가져와서 curst를 만들어서 넣어서
    --strec 레코드를 만든다음에 커스트를 sturec에 밀어넣는것
    --출력하고 curst는 닫는다.


    --과정 1. declare에 curst극 정의한다. student에서 sno, sname, major, syear을 불러온다. sno가 915301인것을
    --strec 레코드를 정의하고 거기 안에 있는 요소들의 타입을 정의 strec의 인스턴스화 sturec를 만듬
    -- curst를 열어서 인스턴스화된 sturec에 집어넣음
    --그걸 출력함


    cursor curst is
        select sno, SNAME, major, syear
        from student
        where sno = '915301';
    type strec is record
                  (
                      sno   varchar2(8),
                      sname varchar2(20),
                      major varchar2(20),
                      syear number(1, 0)

                  );
    sturec strec;
begin
    open curst;
    fetch curst into sturec;
    DBMS_OUTPUT.PUT_LINE(sturec.sno);
    DBMS_OUTPUT.PUT_LINE(sturec.sname);
    DBMS_OUTPUT.PUT_LINE(sturec.major);
    DBMS_OUTPUT.PUT_LINE(sturec.syear);
    close curst;
end;
/


--여러개의 행을담고 있는 커서의 처리 방식;
--1학년인 애들을 다 가져오는거

-- declare에 curst극 정의한다. student에서 sno, sname, major, syear을 불러온다. syear가 1인것을

--로우에 집어넣을껀데 student의 rowtype인 strow를 정의

-- 루프를 만들어서 curst를 열어서 인스턴스화된 strow 집어넣음
--curst에 더이상 정보가 없으면 끝내게
--그걸 출력함

declare
    cursor curst is
        select sno, sname, sex, syear, major, avr
        from student
        where syear = 1;
    strow student%rowtype;
begin
    open curst;
    loop
        fetch curst into strow;
        DBMS_OUTPUT.PUT_LINE(strow.SNO);
        DBMS_OUTPUT.PUT_LINE(strow.SNAME);
        DBMS_OUTPUT.PUT_LINE(strow.SYEAR);
        DBMS_OUTPUT.PUT_LINE(strow.major);

        exit when curst%notfound;
    end loop;
    close curst;
end;
/

--여러행을 담고있는 CUrsor의 for 루프 처리

--여러개의 행을담고 있는 커서의 처리 방식;
--1학년인 애들을 다 가져오는거

-- declare에 curst극 정의한다. student에서 sno, sname, major, syear을 불러온다. syear가 1인것을

--여긴 for문으로 할꺼다
--curse에서 strow를 꺼낸다.
--루프를 열어서
--그걸 출력함

declare
    cursor curst is
        select sno, sname, sex, syear, major, avr
        from student
        where syear = 1;

begin
    --자동 open, fetch, close 일어난다.
--월신 간단함. 변수 선언 해줄필용도없고....
    for strow in curst
        loop
            DBMS_OUTPUT.PUT_LINE(strow.SNO);
            DBMS_OUTPUT.PUT_LINE(strow.SNAME);
            DBMS_OUTPUT.PUT_LINE(strow.SYEAR);
            DBMS_OUTPUT.PUT_LINE(strow.major);

        end loop;
end;
/

--커서의 파라미터
-- 고정된 쿼리 결과가 아닌 유동적인 쿼리의 결과를 커서에 담아준다.
-- 유동적인 데이터를 가져올 수 있는 커서를 만들 수 있음
--curst(param) 에 파라미터 안에 syear을 넣어서 정보를 가져오고싶다.
--cursor를 정의. sno, sname, major, syear를 가져올 수 있또록. 그리고 strec 레코드를 정의  그리고 strec sturec로 인스턴스화
-- curst(2)를 열고 curst를 sturec를 넣어서 출력함
--curst를 닫음
-- 또 curst(4)를 열고 가져오고 닫음


declare
    cursor curst (param_syear number) is
        select sno, sname, major, syear
        from student
        where syear = param_syear;
    type strec is record
                  (
                      sno   student.sno%type,
                      sname student.sname%type,
                      major student.major%type,
                      syear student.syear%type
                  );
    sturec strec;
    --패치로 한줄씩 받아야하니까
begin
    open curst(2);

    loop
        fetch curst into sturec;
        exit when curst%notfound;
        DBMS_OUTPUT.PUT_LINE('-----------------------------------------------2학년데이터');

        DBMS_OUTPUT.PUT_LINE(sturec.SNO);
        DBMS_OUTPUT.PUT_LINE(sturec.SName);
        DBMS_OUTPUT.PUT_LINE(sturec.MAJOR);
        DBMS_OUTPUT.PUT_LINE(sturec.Syear);

    end loop;
    close curst;


    open curst(4);

    loop
        fetch curst into sturec;
        exit when curst%notfound;
        DBMS_OUTPUT.PUT_LINE('-----------------------------------------------4학년데이터');

        DBMS_OUTPUT.PUT_LINE(sturec.SNO);
        DBMS_OUTPUT.PUT_LINE(sturec.SName);
        DBMS_OUTPUT.PUT_LINE(sturec.MAJOR);
        DBMS_OUTPUT.PUT_LINE(sturec.Syear);

    end loop;
    close curst;

end;


/


--묵시적 커서
--실행된 쿼리문의 결과를 담고있는 커서
--따로 커리를 선언하지 않는다.

-- student에서 syear가 0인걸 다 1로 바꿔라;
--바뀐 row가 몇개인지 나오게



--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
begin
    update student
    set syear = 1
    where syear = 0;
    DBMS_OUTPUT.PUT_LINE(sql%rowcount);


end;


select *
from student
where syear = 0;

--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐
--------------------------이거 왜 rowcount 안돼냐


-- 1-9 예외처리
--     -exception으로 예외처리
declare
    val_sno number;
begin
    select sname
    into val_sno
    from student
    where sno = '915301';

    DBMS_OUTPUT.PUT_LINE('예외발생 시 실행안됨');
exception
    when VALUE_ERROR then
        DBMS_OUTPUT.PUT_LINE('수치가 부적합합니다');
        rollback;
end;
/


--update시 에러발생 처리 rollback
--- val_sno가 'A'인데 student의 syear에 넣는다. 예외처리 나오고 sqlcode, sqleerm 나오게 해라 롤백도 하게 해라

declare
    val_sno varchar2(10);
begin
    --숫자에 A를 넣을수 없으니 익셈션 발생할테니 수치부적함 하고 롤백 완료될꺼다 아마
    val_sno := 'A';

    update student
    set syear = val_sno
    where sno = '915301';

    DBMS_OUTPUT.PUT_LINE('예외발생 시 실행안됨');
exception
    when INVALID_NUMBER then
        DBMS_OUTPUT.PUT_LINE('수치가 부적합합니다');
        rollback;
        DBMS_OUTPUT.PUT_LINE('롤백완료');
end;
/

declare
    val_sno varchar2(10);
begin
    --숫자에 A를 넣을수 없으니 익셈션 발생할테니 수치부적함 하고 롤백 완료될꺼다 아마
    val_sno := 'A';

    update student
    set syear = val_sno
    where sno = '915301';

    DBMS_OUTPUT.PUT_LINE('예외발생 시 실행안됨');
exception
    when value_error then
        DBMS_OUTPUT.PUT_LINE('수치가 부적합합니다');
        rollback;
        DBMS_OUTPUT.PUT_LINE('롤백완료');
    when too_many_rows then
        DBMS_OUTPUT.PUT_LINE('수치가 부적합합니다');
        rollback;
        DBMS_OUTPUT.PUT_LINE('롤백완료');
    when program_error then
        DBMS_OUTPUT.PUT_LINE('수치가 부적합합니다');
        rollback;
        DBMS_OUTPUT.PUT_LINE('롤백완료');
    when others then
        DBMS_OUTPUT.PUT_LINE(sqlcode);
        DBMS_OUTPUT.PUT_LINE(sqlerrm);

        rollback;
        DBMS_OUTPUT.PUT_LINE('롤백완료');
end;
/

-----------------------왜 안들어갈텐데 롤백을 해야 하는ㄴ지!?!?!?
-----------------------그냥 엑셉션 다 합해진 에러 없는지?!!?!?!?!!?
-----------------------왜 안들어갈텐데 롤백을 해야 하는ㄴ지!?!?!?
-----------------------그냥 엑셉션 다 합해진 에러 없는지?!!?!?!?!!?-----------------------왜 안들어갈텐데 롤백을 해야 하는ㄴ지!?!?!?
-----------------------그냥 엑셉션 다 합해진 에러 없는지?!!?!?!?!!?-----------------------왜 안들어갈텐데 롤백을 해야 하는ㄴ지!?!?!?
-----------------------그냥 엑셉션 다 합해진 에러 없는지?!!?!?!?!!?

 

댓글 영역