OracleServiceXE, OracleXETNSListener 실행시키기
-- 게시판 운영 쿼리
-- 데이터 - 글번호, 제목, 내용, 작성자, 작성일, 조회수, 비밀번호
-- 1. 게시판 리스트
-- 번호, 제목, 작성자, 작성일, 조회수
select no, title, writer, writeDate, hit -- 보여줄 항목 선택
from board -- 데이터가 저장되어 있는 곳
order by no desc; -- 정렬 방법(최신글을 맨위에)
-- 2. 게시판 글보기 + 조회수 증가
-- 번호, 제목, 내용, 작성자, 작성일, 조회수 - 보고자 하는 데이터:글번호가 2번
select no, title, content, writer, writeDate, hit -- 보여줄 항목 선택
from board -- 데이터가 저장되어 있는 곳
where no = 2; -- 보고자 하는 데이터:글번호가 2번
-- 조회수 1 증가 - > hit = hit + 1
update board set hit = hit + 1
where no = 2;
commit;
-- 3. 게시판 글쓰기 - 비밀번호 필요
insert into board(no, title, content, writer, pw)
values(board_seq.nextval, '게시판입니다.', '좋은 글을 공유합니다.', '이영환', '1111');
commit;
-- 4. 게시판 글수정 - 비밀번호 필요
-- 글번호와 비밀번호가 맞아야 수정해 준다. 수정 항목 - 제목, 내용, 작성자
update board set title = '게시판입니다.', content = '게시판 완성', writer = '개발자'
where no = 2 and pw = '1111';
commit;
-- 5. 게시판 글삭제 - 비밀번호 필요
-- 글번호가 2번인 글 지우자. 비밀번호가 맞아야 한다.
delete from board
where no = 2 and pw = '1111';
rollback; -- 실행된 내용 취소
계정 생성시 롤 SYSDBA
호스트 이름 localhost
포트 1521
SID xe
-> jdbc:oracle:thin:@localhost:1521:xe
계정 만들고 권한주기
-- 계정 만들기
CREATE USER java IDENTIFIED BY java;
-- 권한 주기 (연결, 자원관리, 뷰 테이블 만들기)
GRANT CONNECT, RESOURCE, CREATE VIEW TO java;
VARCHAR2
: 4000자 입력 가능한 문자열
NOT NULL
등 제약조건
NUMBER(3)
: 3자리 입력
PK
- primary key : 중복 안됨, null 안됨 -> 키로 지정
FK
- foriegn key : 다른테이블 컬럼에 데이터가 존재, null 가능
ON DELETE CASCADE
- 부모가 삭제되면 같이 삭제
ON DELETE SET NULL
- NOT NULL
이 붙어 있으면 안됨. 부모가 삭제되면 NULL로 세팅한다.
기본
- 데이터를 사용하는 경우 부모는 삭제가 안된다. (자식 데이터를 먼저 지우고 부모데이터를 지워야만 한다.)
UK
- unique : 중복 안됨. ex) 주민등록번호, 핸드폰번호 등
CK
- check (조건) ex) score number(3) check (score >= 0 and score <= 100)
-정규표현식 잘 활용하기
SELECT * FROM COL WHERE TNAME = 'BOARD';
SELECT * FROM COL WHERE TABLE_NAME = 'BOARD';
: BOARD 테이블의 스키마를 보여줌
SQL query - SELECT : WHERE and / or (=in)
gender가 남자 또는 여자이어야 한다.
-- or : WHERE GENDER ='여자' OR GENDER ='남자'
-- in : WHERE GENDER IN ('여자','남자')
score가 0부터 100사이의 데이터
-- and : WHERE SCORE >=0 AND SCORE <= 100
-- between : WHERE SCORE BETWEEN 0 AND 100
현재 공지 : TRUNC()를 사용해서 BETWEEN을 이용한 쿼리 작성
-- and : WHERE startDate <= SYSDATE AND TRUNC(SYSDATE) <= endDate
-- between : WHERE TRUNC(SYSDATE) BETWEEN startDate and endDate
score의 합계, 평균, 최소점, 최고점, 갯수를 구하는 SELECT 문 작성
-- 테이블 이름 : scores
-- 합계 : SELECT SUM(score) FROM SCORES
-- 평균 : SELECT AVG(score) FROM SCORES
-- 최고점 : SELECT MAX(score) FROM SCORES
-- 최소점 : SELECT MIN(score) FROM SCORES
-- 갯수 : SELECT COUNT(score) FROM SCORES
AVG와 COUNT는점수가 null인 경우 세지 않음
-- scores (class, score) class 별 합계와 평균을 구하고 class도 출력하는 SQL 문장 작성
: SELECT class, SUM(score), AVG(score) FROM scores GROUP BY class
sub query를 이용한 페이지 처리
-- 1페이지 10개씩 : 1~10번, 2페이지 11~20번
1. 제일 큰 번호를 맨 위로 정렬시켜서 데이터를 가져온다.
2. 1번 데이터에 순서 번호를 붙인다. ROWNUM RNUM
3. 1페이지에 해당하는 데이터 10개 가져오기. RNUM이 1~10번까지 인 데이터.
-- 페이징 처리하기 (한페이지에 10개씩만 보이기)
-- board 데이터 늘리기 - 서브쿼리
INSERT INTO board (no, title, content, writer, pw)
(select board_seq.nextval, title, content, writer, pw from board);
COMMIT;
SELECT * FROM board;
SELECT COUNT(*) FROM board;
-- 1페이지에 해당되는 데이터 가져오기 : Oracle, mySQL, MS SQL이 페이징 처리하는 방법이 각각 다르다.
-- PK INDEX는 Oracle에서 자동으로 만든다. -> 속도가 빨라짐.
-- 추가, 수정, 삭제가 빈번하게 일어나는 데이터와 거의 대부분의 데이터로 검색하는 경우는 INDEX를 만들지 않는게 좋다.
-- : 공간만 많이 차지하고 효율성이 떨어진다.
-- 1. 데이터를 가져와서 최신글부터 보이게 정렬시킨다.
SELECT no, title, writer, writeDate, hit FROM BOARD ORDER BY no DESC;
-- 2. 1번의 데이터를 가지고 순서번호(rnum)를 붙인다. -서브쿼리
-- 예를 들면 가장 최근에 쓰인 160번의 글의 rnum은 1번이 된다.
SELECT ROWNUM rnum, no, title, writer, writeDate, hit
FROM (
-- 1번 데이터
SELECT no, title, writer, writeDate, hit FROM BOARD ORDER BY no DESC
);
-- 3. 2번데이터를 가지고 순서번호가 1~10까지
-- BETWEEN을 사용해서 가져오기
-- 최종적으로 보이는 데이터기 때문에 rnum은 가져오지 않아도 된다.
SELECT rnum, no, title, writer, writeDate, hit
FROM (
-- 2번 데이터
SELECT ROWNUM rnum, no, title, writer, writeDate, hit
FROM (
-- 1번 데이터
SELECT no, title, writer, writeDate, hit FROM BOARD ORDER BY no DESC
)
)
WHERE rnum BETWEEN 1 AND 10; -- 최근에 쓴 글 10개만 가져오기
검색 조건 title과 writer 중에서 java가 포함되어 있는 데이터 가져오기 -like
SELECT no, title, writer, writeDate, hit
FROM board
WHERE title like '%java%' OR writer like '%java%';
VIEW no = 2
SELECT no, title, content, writer, writeDate, hit FROM board
WHERER no = 2;
INSERT
INSERT INTO board (no, title, content, writer, pw)
VALUES (board_seq.nextval, '제목', '내용', '작성자', 'password');
UPDATE
UPDATE board SET title = '제목수정', content = '내용수정', writer = '작성자수정'
WHERE no = 2 AND pw = 'password';
DELETE
DELETE FROM board
WHERE no = 2 AND pw = 'password';
INCREAS
UPDATE board SET hit = hit + 1
WHERE no = 2;
데이터가 입력 오류가 나는 경우 -> 이유 작성하시오.
member table
에서 아이디, 이름, 등급번호를 가져오고 grade table
에서 등급이름을 가져오는 SQL 쿼리 작성
SELECT m.id, m.name, m.gradeNo, g.gradeName
FROM member m, grade g
WHERE g.gradeNo = m.gradeNo;
Outter Join
:g.gradeNo(+)
데이터가NULL
인 경우에는 외부조인(Outter Join
)을 해야한다.NULL
로 조인해서 가져온다.
예를들면 좋아요 기능을 구현할 때 좋아요를 안한 상태에서도 (null) 리스트를 가져와야 한다.
4개의 테이블을 JOIN
하는 경우
FROM t1, t2, t3, t4
WHERE t1.PK = t2.FK AND t2.PK = t3.FK AND t3.PK = t4.FK;
-- 인덱스 생성
-- 게시판으로 만들기
-- 글번호 검색을 많이 한다. -PK이므로 이미 이컬럼으로 만들어 져 있므로 오류가 난다.
CREATE INDEX idx_board_no
ON board(no);
-- 제목 검색
CREATE INDEX idx_board_title
ON board(title);
-- 작성자 검색
CREATE INDEX idx_board_writer
ON board(writer);
-- 제목, 작성자 동시에 검색
CREATE INDEX idx_board_title_writer
ON board(title, writer);
-- ** 검색을 많이하는 테이블인 경우 검색을 많이하는 컬럼을 속도 향상을 위해 인덱스를 만든다.
-- 인덱스 조회
SELECT * FROM USER_INDEXES WHERE TABLE_NAME = 'BOARD';
SELECT * FROM ALL_IND_COLUMNS WHERE TABLE_NAME = 'BOARD';
-- 인덱스 삭제
DROP INDEX idx_board_title;
DROP INDEX idx_board_writer;
DROP INDEX idx_board_title_writer;
PK INDEX
는 Oracle에서 자동으로 만든다. -> 속도가 빨라짐.
추가, 수정, 삭제가 빈번하게 일어나는 데이터와 거의 대부분의 데이터로 검색하는 경우는INDEX
를 만들지 않는게 좋다.
: 공간만 많이 차지하고 효율성이 떨어진다.
-- 점수 처리를 위한 테이블 - 반, 학생번호, 점수
CREATE TABLE scores (
no NUMBER PRIMARY KEY, -- 일련번호, PK를 다른 컬럼에 잡을 수 없을 때 하나 만들어 놓으면 좋다.
class NUMBER(2) NOT NULL, -- 반
sno NUMBER(2) NOT NULL, -- 학생번호, 학생 테이블의 학번 (Join해서 가져온다), REFERENCES
score NUMBER(3) CHECK (score BETWEEN 0 AND 100) NOT NULL -- 점수
); -- DEFAULT는 제약조건(NOT NULL) 앞에 붙인다
CREATE SEQUENCE scores_seq;
-- test 데이터 넣기
-- 차례대로 모든 데이터를 다 넣을 때 컬럼명 생략 가능
INSERT INTO scores VALUES(scores_seq.nextval, 1, 1, 100);
INSERT INTO scores VALUES(scores_seq.nextval, 1, 2, 80);
INSERT INTO scores VALUES(scores_seq.nextval, 2, 3, 90);
INSERT INTO scores VALUES(scores_seq.nextval, 2, 4, 75);
INSERT INTO scores VALUES(scores_seq.nextval, 2, 5, 95);
INSERT INTO scores VALUES(scores_seq.nextval, 3, 6, 100);
INSERT INTO scores VALUES(scores_seq.nextval, 3, 7, 70);
COMMIT;
SELECT * FROM scores;
-- 전체 학년의 통계치
-- score의 합계, 평균(소수점 아래 두자리 까지만), 최소값, 최대값, 컬럼갯수
-- '999.00' : 9를 쓰면 비어서 나오고, 0이라고 쓰면 0을 넣는다.
-- 예를 들면 평균이 87.14일 때 '099.00' 이라고 쓰면 087.14가 나온다.
SELECT SUM(score) 합계, TO_CHAR(AVG(score), '999.00') 평균, MIN(score) 최소점, MAX(score) 최고점, COUNT(score) 응시인원
FROM scores;
-- scores 테이블의 반 별 통계치
SELECT class 반, SUM(score) 합계, TO_CHAR(AVG(score), '999.00') 평균, MIN(score) 최소점, MAX(score) 최고점, COUNT(score) 응시인원
FROM scores
GROUP BY class;
-- member 테이블의 성비율 통계
SELECT gender 성별, COUNT(*) 인원
FROM member
GROUP BY gender;
-- 나이대별 통계
-- 10대, 20대, 30대, 40대, 50대 60대, 70대, 80대, 90대
-- 나이 컬럼이 존재해야 한다.
-- 10대 찾는 계산 -> (나이 / 10) -> 소수점 절사 trunc() -> 곱하기 10
-- ex) 24/10= 2.4 -> 소수점 절사하면 2 -> 2 * 10 -> 20대
-- score 테이블의 점수대 별 통계
-- 100점대의 갯수, 90점대의 갯수, 80점대의 갯수, 70점대의 갯수
-- " " 안에 넣으면 대소문자 구분하고 빈칸도 넣을 수 있다.
SELECT (TRUNC (score / 10) *10) "Score Area", COUNT(*) count
FROM scores
GROUP BY (TRUNC (score / 10) *10)
ORDER BY "Score Area" DESC;