DECLARE
sum1 NUMBER := 0;
CURSOR dept_cnt IS SELECT deptno, dname FROM DEPT;
BEGIN
FOR dept IN dept_cnt LOOP
IF(mod(dept.deptno,4) = 0) THEN
sum1 := sum1 + dept.deptno;
END IF;
DBMS_OUTPUT.put('부서번호 : ' || TO_CHAR(dept.deptno));
DBMS_OUTPUT.PUT_LINE('부서이름 : ' || dept.dname);
END LOOP;
DBMS_OUTPUT.put_line('4의 배수인 부서번호의 합계: ' || TO_CHAR(sum1));
END;
CREATE or replace TRIGGER sal_trigger
BEFORE
INSERT OR UPDATE
ON EMP
FOR EACH ROW
DECLARE
disable_sal EXCEPTION;
BEGIN
IF :new.sal < 10 THEN
RAISE disable_sal;
END IF;
EXCEPTION
WHEN disable_sal THEN
RAISE_APPLICATION_ERROR(-20500, '급여 부족');
END;
/*
여러 행을 반환하는 select문은 cursor를 이용해야 할 것 같아서 자료를 보고 따라하는데 프로시저는 DECLARE를
하지 않아서 계속 문법오류가 나서 오래 걸렸다. 프로시저의 IS에 같이 선언하면 된다.
*/
CREATE OR REPLACE PROCEDURE SelectTimeTable(sStudentId IN CHAR, -- 학번
nYear IN NUMBER,-- 학년도
nSemester IN NUMBER) -- 학기
IS
sId COURSE.C_ID%TYPE; -- 과목번호
sName COURSE.C_NAME%TYPE; -- 과목명
nUnit COURSE.C_UNIT%TYPE; -- 학점
nTime TEACH.T_TIME%TYPE; -- 교시
sWhere TEACH.T_WHERE%TYPE; -- 강의실
nTotUnit NUMBER := 0; -- 총학점
CURSOR course_all is
SELECT e.c_id, c.c_name, c.c_unit, t.t_time, t.t_where
-- 과목번호, 과목명, 학점, 교시, 강의실
FROM enroll e, course c, teach t
WHERE e.c_id = c.c_id and e.c_id = t.c_id and
e.s_id = sStudentId and e.e_year = nYear and e.e_semester=nSemester and
t.t_year = nYear and t.t_semester = nSemester
ORDER BY 4;
BEGIN
OPEN course_all;
DBMS_OUTPUT.put_line('<수강신청 시간표>');
DBMS_OUTPUT.put_line('학번:' || sStudentId);
DBMS_OUTPUT.put_line('년도:' || TO_CHAR(nYear));
DBMS_OUTPUT.put_line('학기:' || TO_CHAR(nSemester));
LOOP
FETCH course_all INTO sId, sName, nUnit, nTime, sWhere;
EXIT WHEN course_all%NOTFOUND;
DBMS_OUTPUT.put_line('교시:' || TO_CHAR(nTime) ||
', 과목번호:' || sID ||
', 과목명:'|| sName ||
', 학점:' || TO_CHAR(nUnit) ||
', 강의실:' || sWhere);
nTotUnit := nTotUnit + nUnit;
-- 학점 합계 구하기(nUnit 변수를 이용하여, nTotUnit 변수에 총합 저장)
END LOOP;
DBMS_OUTPUT.put_line('총 ' || TO_CHAR(course_all%ROWCOUNT) || ' 과목과 총 ' ||
TO_CHAR(nTotUnit) || '학점을 신청하였습니다.');
CLOSE course_all;
END;
CREATE OR REPLACE FUNCTION Date2EnrollYear(dDate IN DATE)
RETURN NUMBER
IS
nYear NUMBER;
sMonth CHAR(2);
BEGIN
/* 10월 ~ 12월 : 매개변수로 받은 날짜의 다음 년도, 10월~12월 외 : 매개변수로 받은 날짜의 년도 */
nYear := EXTRACT(YEAR FROM dDate); -- 매개변수로 받은 날짜 중 '년도' 추출
sMonth := TO_CHAR(EXTRACT(MONTH FROM dDate)); -- 매개변수로 받은 날짜 중 '월' 추출
IF (sMonth='10' or sMonth='11' or sMonth='12') THEN
nYear := nYear + 1;
END IF;
RETURN nYear;
END;
CREATE OR REPLACE FUNCTION Date2EnrollSemester(dDate IN DATE)
RETURN NUMBER
IS
nSemester NUMBER;
sMonth CHAR(2);
BEGIN
/* 10월 ~ 12월 : 매개변수로 받은 날짜의 다음 년도, 10월~12월 외 : 매개변수로 받은 날짜의 년도 */
sMonth := TO_CHAR(EXTRACT(MONTH FROM dDate)); -- 매개변수로 받은 날짜 중 '월' 추출
IF (sMonth='10' or sMonth='11' or sMonth='12' or sMonth='1' or sMonth='2' or sMonth='3') THEN
nSemester := 1;
ELSE
nSemester := 2;
END IF;
RETURN nSemester;
END;
CREATE OR REPLACE PROCEDURE InsertEnroll(sStudentId IN CHAR, -- 학번
sCourseId IN CHAR, -- 과목번호
result OUT VARCHAR2) -- 입력 결과 메시지
IS
too_many_sumCourseUnit EXCEPTION;
too_many_courses EXCEPTION;
too_many_students EXCEPTION;
duplicate_time EXCEPTION;
nYear NUMBER; -- 수강신청 년도
nSemester NUMBER; -- 수강신청 학기
nSumCourseUnit NUMBER; -- 수강신청완료된 과목들의 총학점
nCourseUnit NUMBER; -- 학점
nCnt NUMBER;
nTeachMax NUMBER; -- (수강신청 년도,학기,과목에 대한) 최대 학생수(최대 정원)
BEGIN
result := '';
DBMS_OUTPUT.put_line('#');
DBMS_OUTPUT.put_line(sStudentId || '님이 과목번호 ' || sCourseId || '의 수강 등록을 요청하였습니다.');
/* (수강신청하는 오늘 날짜를 기준으로) 수강신청 년도, 학기 알아내기 : 함수 사용 */
nYear := Date2EnrollYear(SYSDATE); -- 수강신청 년도
nSemester := Date2EnrollSemester(SYSDATE); -- 수강신청 학기
/* 에러 처리 1 : 최대학점(18학점) 초과 여부 검사 */
-- (수강신청 년도, 학기에 해당 학생의) 수강신청 완료(enroll 테이블에 저장 완료)된 과목들의 총학점
SELECT SUM(c.c_unit)
INTO nSumCourseUnit
FROM course c, enroll e
WHERE e.s_id = sStudentId and e.e_year = nYear and e.e_semester = nSemester
and e.c_id = c.c_id;
-- 현재 수강신청을 하려고 하는 과목의 학점을 검색하여 nCourseUnit 변수에 저장
SELECT c_unit
INTO nCourseUnit
FROM course
WHERE c_id = sCourseId;
-- 수강신청 완료된 과목들의 총학점 + 현재 수강신청을 하려고 하는 과목의 학점 > 18인지 검사
IF (nSumCourseUnit + nCourseUnit > 18) THEN
RAISE too_many_sumCourseUnit;
END IF;
/* 에러 처리 2 : 동일한 과목 신청 여부 검사 */
-- 해당 학생의 수강신청 완료(enroll 테이블에 저장 완료)된 과목 중, 현재 수강신청을 하려고 하는 과목이 있는지 검사
SELECT COUNT(*)
INTO nCnt
FROM enroll
WHERE s_id = sStudentId and c_id = sCourseId;
IF (nCnt > 0)
THEN
RAISE too_many_courses;
END IF;
/* 에러 처리 3 : 수강신청 인원 초과 여부 검사 */
-- (수강신청 년도,학기,과목에 대한) 최대 학생수(최대 정원) 검색
SELECT t_max
INTO nTeachMax
FROM teach
WHERE t_year= nYear and t_semester = nSemester and c_id = sCourseId;
-- (수강신청 년도,학기,과목으로) 이미 수강신청 완료(enroll 테이블에 저장 완료)된 학생수 검색하여 nCnt 변수에 저장
SELECT COUNT(*)
INTO nCnt
FROM enroll
WHERE e_year = nYear and e_semester = nSemester and c_id = sCourseId;
-- (수강신청 년도,학기,과목에 대한) 수강신청 완료 학생수 >= (수강신청 년도,학기,과목에 대한)최대 학생수 인지 검사
IF (nCnt >= nTeachMax)
THEN
RAISE too_many_students;
END IF;
/* 에러 처리 4 : 신청한 과목들 시간 중복 여부 */
-- (수강신청 년도,학기에) 수강신청하려고 하는 과목의 교시(수업시간)와
-- (수강신청 학생,년도,학기로) 이미 수강신청 완료된 과목들의 교시(수업시간)
-- 중 중복되는 교시(수업시간)가 있는지 검사
SELECT COUNT(*)
INTO nCnt
FROM
(
SELECT t_time
FROM teach
WHERE t_year=nYear and t_semester = nSemester and c_id = sCourseId
INTERSECT
SELECT t.t_time
FROM teach t, enroll e
WHERE e.s_id=sStudentId and e.e_year=nYear and e.e_semester = nSemester and
t.t_year=nYear and t.t_semester = nSemester and
e.c_id=t.c_id
);
IF (nCnt > 0)
THEN
RAISE duplicate_time;
END IF;
/* 수강 신청 : Enroll 테이블에 학번,과목번호,수강년도, 수강학기 입력 */
INSERT INTO enroll VALUES(sStudentId, sCourseId, nYear, nSemester);
COMMIT;
result := '수강신청 등록이 완료되었습니다.';
EXCEPTION
WHEN too_many_sumCourseUnit THEN
result := '최대학점을 초과하였습니다';
WHEN too_many_courses THEN
result := '이미 등록된 과목을 신청하였습니다';
WHEN too_many_students THEN
result := '수강신청 인원이 초과되어 등록이 불가능합니다';
WHEN duplicate_time THEN
result := '이미 등록된 과목 중 중복되는 시간이 존재합니다';
WHEN OTHERS THEN
result := SQLCODE;
END;
CREATE or REPLACE TRIGGER BeforeUpdateStudent
BEFORE UPDATE ON student
FOR EACH ROW
DECLARE
underflow_length EXCEPTION;
invalid_value EXCEPTION;
nLength NUMBER;
nBlank NUMBER;
BEGIN
/* 암호 제약조건 : 4자리 이상, blank는 허용안함 */
/* 오라클 내장함수
length(문자열) => 문자열의 길이
instr(문자열1, 문자열2) => 문자열1에서 문자열2가 나타난 첫번째 위치
*/
nLength := length(:new.s_pwd);
nBlank := instr(:new.s_pwd , ' ');
IF nLength < 4 THEN
RAISE underflow_length;
ELSIF (nBlank > 0) THEN
RAISE invalid_value;
END IF;
EXCEPTION
WHEN underflow_length THEN
RAISE_APPLICATION_ERROR(-20002, '암호는 4자리 이상이어야 합니다');
WHEN invalid_value THEN
RAISE_APPLICATION_ERROR(-20003, '암호에 공란은 입력되지 않습니다.');
END;
빅데이터
좁은 정의: 대규모 데이터
넓은 정의: 대규모 데이터를 저장 및 관리하는 기술과 가치있는 정보를 만들기 위해 분석하는 기술까지 포함
빅데이터 특징 5V
- Volume(규모) : 증가된 데이터양
- Variety(다양성) : 데이터 형태의 다양성
- Velocity(속도) : 빨라진 데이터의 생성 속도
- Value(가치) : 데이터의 가치
- Veracity(정확성) : 데이터의 정확성
NoSQL: 빠른 속도로 생성되는 대량의 비정형 데이터를 저장하고 처리하기 위해 ACID(원자성, 일관성, 격리성, 지속성)를 위한 트랜잭션 기능을 제공하지 않는 대신, 저렴한 비용으로 여러대의 컴퓨터에 데이터를 분산∙저장∙처리하는 것이 가능한 데이터베이스
장점: 유연성(변경이 자유로움), 확장성(서버 추가 용이,클러스터), 경제성(오픈 소스)
NoSQL 종류
- 키-값(key-value) 데이터베이스: 레디스(Redis), 다이나모(Dynamo)
- 키와값의쌍으로데이터가저장됨
- 질의처리속도빠름
- 키를사용해서만검색(값을사용한검색안됨)
- 문서기반(document-based) 데이터베이스: 몽고DB(MongoDB), 카우치DB(CouchDB)
- 키와문서의쌍으로데이터를저장
- 트리형태의계층적구조가존재하는 JSON, XML 등과같은반정형 (semi-structured) 데이터 형태로 트리 형태의계층적구조
- 컬럼기반(column-based) 데이터베이스: 카산드라(Cassandra), HBase
- 컬럼패밀리는관련있는컬럼값들을모아서구성
- 그래프기반(graph-based) 데이터베이스: Neo4j
- 데이터를데이터간의관계와함께표현
- 질의는그래프순회과정을통해처리
- SNS 에서친구찾기질의등을수행하는데적합
Mongo DB
데이터 구조: 데이터베이스 안에 컬렉션, 컬렉션 안에 문서가 포함된 계층적 구조
- 문서(document)
- { 필드이름: 필드값}
- JSON(JavaScript Object Notation) 타입을 바탕으로 함
- 컬렉션(collection)
- 문서들의 모임
- 같은 컬렉션 안에 저장되는 문서 구조가 다양할 수 있음
db.createCollection(“회원”) // 컬렉션 생성(컬렉션 이름: 회원)
db.회원.InsertMany( [
{_id:1, 회원이름:"홍길동", 비밀번호:11, 나이:23, 성별:"남"},
{_id:2, 비밀번호:23, 나이:25, 성별:"여", 직업:"유투버"}
])
db.회원.find({나이:23})
// 문서 삽입
// 문서검색
db.회원.updateMany({성별:"남"}, {$set:{성별:"M", 비밀번호:0}}) // 문서수정
db.회원.deleteMany({나이 : 23})
db.회원.drop()
// 컬렉션삭제(컬렉션‘회원’삭제
벡터 데이터베이스: 비정형데이터를수치적표현인벡터(벡터임베딩 이라고도함) 형태로정보를저장하여다양한분석 및처리작업을수행하는데이터베이스, SQL이아닌, 벡터유사도를기반으로데이터검색
벡터 임베딩
- 비정형데이터를고차원수치벡터로변환하는기술
- 임베딩모델이자동생성
'database' 카테고리의 다른 글
| SQL 문법 정리 (0) | 2025.06.13 |
|---|---|
| 데이터베이스 개념 (0) | 2025.06.13 |
| 데이터베이스 성능 향상[Index] (0) | 2025.06.11 |
| Transaction(트랜잭션) (0) | 2025.06.11 |
| PL/SQL (프로시저, 함수, 트리거) (0) | 2025.06.11 |
