티스토리 뷰
sql문의 분류
DDL: Data Definition Language
- Create문: 테이블 및 각종 객체를 새로 만든다.
- Drop문: 테이블 및 각종 객체를 없앤다.
- Alter문: 테이블 및 각종 객체의 구조를 바꾼다.
DML: Data Manipulation Language
- Insert문: 새로운 레코드 삽입
- Delete문: 레코드 삭제
- Update문: 레코드 내의 특정값을 변경
DCL: Data Control Language
- Commit: 트랜잭션 완료
- Roll Back: 다시 돌아감
DQL: Data Query Language
- Select
- DQL을 따로 정의하지 않는 DML로 봄.
테이블 스키마는 속성의 집합으로 표현이 된다.
Create and Drop
자료형(Data type)
- 테이블을 생성할 때 각 속성마다 형태와 크기를 정해주어야 한다.
- 속성에 들어갈 값의 형태와 크기를 고려하여 자료형을 정한다.
많이 쓰는 자료형
- char(n): fixed-length character string
- varchar2(n): variable-length character string
- int, smallint
- numeric(p, d), number(p, d), decimal(p, d), dec(p, d)
- real, double, float(p)
- 오라클에는 int가 없어 int로 저장하면 알아서 num으로 변경해줌.
Create
Create table ~
- 테이블 스키마를 생성
- 그 외의 객체들도 생성할 때 Create를 사용한다.
- 속성 이름이 자료형보다 먼저 옴.
- foreign key 테이블 이름 뒤에 속성을 지정하지 않으면 그 테이블의 기본키를 참조하는 것이다.
수강 과목 학생
- 생성시: 학생->수강
- 삭제시: 수강->학생
구조
create table 테이블_이름 (
속성_이름1 자료_형1,
속성_이름2 자료_형2,
...,
primary key (속성11, 속성12, ...),
foreign key (속성21, 속성22, ...) references 테이블_이름2
);
-- 학생 테이블
create table 학생 (
학번 varchar2(7),
이름 varchar2(20),
학과번호 varchar2(3),
이수학점 int,
평점 float,
primary key (학번)
);
-- 과목 테이블
create table 과목 (
과목번호 varchar2(5),
과목이름 varchar2(30),
최대인원 int,
primary key (과목번호)
);
-- 수강 테이블
create table 수강 (
학번 varchar2(7),
과목번호 varchar2(5),
primary key (학번, 과목번호),
foreign key (학번) references 학생,
foreign key (과목번호) references 과목
);
✅ 공통 속성의 자료형은 똑같아야 한다.
- 학생 테이블의 학번이 varchar2(7)이면 수강 테이블의 학번도 varchar2(7)이어야 한다.
Drop
Drop table 테이블이름;
- 테이블 내의 데이터를 포함, 스키마까지 모두 삭제
- 그 외의 객체들도 삭제할 때 Drop을 사용한다.
- Create는 여러 가지 문법 구조를 가지지만 Drop은 단순하다.
⚠️ 여러 개의 테이블을 만들거나 지울 때 주의할 점
- 여러 개의 테이블을 만들 때 어떤 테이블에 외래 키가 있을 경우,
- 예를 들어 테이블 A의 기본 키인 속성이 B에 있을 경우,
- A를 먼저 만들어야 B에서 외래 키 지정을 할 수 있다.
- 반대로 지울 때는 B에 있는 외래 키 지정 때문에 A는 바로 지워지지 않는다. 따라서 B부터 지워야 한다.
Insert
구조
Insert into 테이블_이름
(속성_이름1, 속성_이름2, ...,) values (값1, 값2, ...);
- 속성 이름들을 지정하지 않으면 Create할 때 설정했던 속성 순서대로 값들만 지정
- 속성 이름들을 지정했을 경우 지정되지 않은 속성에는 null이 들어간다.
- 일부러 null을 집어넣을 수도 있다.
-- 학번이 '9966666', 이름이 '이순신', 이수학점이 0, 평점이 0.0인 레코드를 학생 테이블에 삽입(학과번호는 null)
Insert into 학생 values ('9966666', '이순신', null, 0, 0);
Insert into 학생 (이름, 학번, 평점, 이수학점) values ('이순신', '9966666', 0, 0);
NULL의 특성
- 어떤 레코드는 삽입되었는데 그 중 특정 속성에 값이 들어있지 않다는 의미
- null인 속성에 대한 비교 연산의 결과는 모두 false
- null인지 아닌지 비교하는 구문 : Is null, Is not null
Select * from 학생 where 학과번호 = '010';
Select * from 학생 where 학과번호 != '010';
Select * from 학생 where 학과번호 is null;
Update
- 이미 입력된 레코드의 빈 속성에 값을 넣거나 속성 하나의 값을 삭제하는 것은 Update이다.
- 정확한 레코드를 where 절을 통해 선택
- where 절 없으면 모든 레코드가 선택됨
- =는 비교연산자가 아니라 대입연산자가 된다.
- 행에 있는 값을 변경
구조
Update 테이블_이름 Set
속성1 = 값1, 속성2 = 값2, ...
Where 조건1 (and/or) 조건2 (and/or) ...;
Update 학생 set 학과번호 = '030' where 학번 = '9966666';
Update 학생 set 이수학점 = 이수학점 + 20;
Delete
- 조건이 없으면 모든 레코드를 삭제
- Drop은 스키마도 없애지만 Delete는 레코드만 삭제
- delete는 레코드 단위로 삭제하므로 delete와 from 사이에 아무것도 없다.
- delete from 하고 where 절을 안쓰면, 스키마는 남아있지만 레코드는 다 삭제된 것
- drop은 스키마까지 다 삭제함.
구조
Delete From 테이블_이름
Where 조건1 (and/or) 조건2 (and/or) ...;
Delete from 학생 where 학번 = '9966666';
✅ insert와 delete는 레코드 단위로 삽입, 삭제가 발생한다.
이미 있는 테이블을 이용하여 새 테이블 만들기
Create table 테이블_이름 as [sub-query];
Create table SW공학과학생 as
select * from 학생 where 학과번호 = '010';
sub-query에 의한 insert
Insert into 테이블 [(컬럼1, 컬럼2, 컬럼3...)]
[sub-query];
Insert into SW공학과학생 (학번, 이름, 학과번호)
Select 학번, 이름, 학과번호 from 학생
where 학과번호 = '020';
- 일반적인 방법과는 달리 VALUES절을 사용하지 않는다.
- Insert절에 명시된 컬럼 수가 sub-query에 사용된 컬럼 수와 일치해야 하며 데이터 타입도 일치해야 한다.
- sub-query가 리턴하는 행 수만큼 입력된다.
합집합, 교집합, 차집합
Union(합집합)
- 두 개의 select문이 결과 속성 집합이 같을 때, 두 결과 집합에 대해 합집합이 가능
- 이 때 사용하는 키워드가 Union
- Union all 키워드를 쓰면 중복되는 데이터를 중복되는 횟수만큼 보여준다.
select 학번, 이름 from 학생
where 학과번호 = '010'
union
select 학번, 이름 from 학생
where 이수학점 >= 100;
->
select 학번, 이름 from 학생
where 학과번호 = '010' or 이수학점 >= 100;
Intersect(교집합)
- 두 개의 select문의 결과 속성 집합이 같을 때, 두 결과 집합에 대해 교집합이 가능
- 이 때 사용하는 키워드가 Intersect
- 자연 조인보다 intersect를 쓰는 것이 좋음.
select 학번, 이름 from 학생
where 학과번호 = '010'
intersect
select 학번, 이름 from 학생
where 이수학점 >= 100;
->
select 학번, 이름 from 학생
where 학과번호 = '010' and 이수학점 >= 100;
Minus(차집합)
- 두 개의 select문의 결과 속성 집합이 같을 때, 두 결과 집합에 대해 차집합이 가능
- 이 때 사용하는 키워드가 Minus
select 학번, 이름 from 학생
where 학과번호 = '010'
minus
select 학번, 이름 from 학생
where 이수학점 >= 100;
->
select 학번, 이름 from 학생
where 학과번호 = '010' and 이수학점 < 100;
합집합, 교집합, 차집합의 유용성
-- 학과번호가 '020'인 학생 중에 과목번호 'cs300'인 과목을 수강하는 학생의 학번을 찾으시오.
select 학생.학번 from 학생, 수강
where 학생.학번 = 수강.학번
and 수강.과목번호 = 'cs300'
and 학생.학과번호 = '020';
select 학번 from 학생 where 학과번호 = '020';
intersect
select 학번 from 수강 where 과목번호 = 'cs300';
통계 함수
대표적인 통계 함수
- sum: 그 속성의 합계를 구한다.
- count: 투플의 수를 구한다.
- avg: 그 속성의 평균값을 구한다.
- min: 그 속성의 최솟값을 구한다.
- max: 그 속성의 최대값을 구한다.
count
-- 학생들의 수강 신청한 내역의 개수를 보여주는 SQL문을 만드시오
select count(*) as 수강신청건수 from 수강;
-- 학번이 '9912345'인 학생이 몇 과목을 신청했는지 구하는 SQL문을 만드시오.
select count(*) as 수강신청건수 from 수강
where 학번 = '9912345';
sum, avg
-- 학과번호가 '010'인 학생들의 이수학점 합계를 구하는 SQL문을 만드시오.
select sum(이수학점) as 이수학점합계 from 학생
where 학과번호 = '010';
-- 학과번호가 '010'인 학생들의 이수학점 평균을 구하는 SQL문을 만드시오.
select avg(이수학점) as 이수학점합계 from 학생
where 학과번호 = '010';
통계 함수의 처리
Group by
group by 절이 없을 때
- 그 속성에 대한 통계값을 구함
group by 절이 있을 때
- group by 뒤에 나오는 속성으로 투플들을 나눔
- 각 그룹별로 통계값을 구함
- 그룹 기준이 되는 속성 이외의 속성을 표시할 수 없음
- group by 앞에 where 절이 있으면 where 절 수행 후 group by
-- 학과번호별로 이수학점의 합계를 구하는 SQL문을 만드시오.
select 학과번호, sum(이수학점) as 이수학점합계
from 학생 group by 학과번호;
- 일반적인 속성과 통계값은 같이 select 할 수 없지만, group 기준이 되는 속성은 같이 select 할 수 있다.
- 아래 예는 오류 발생
-- 학과번호가 '010'가 아닌 학생들의 학번과 이수학점 합계를 구하는 SQL문을 만드시오.
select 학번, sum(이수학점) as 이수학점합계
from 학생 where 학과번호 != '010'
group by 학과번호;
Having
- 통계 함수를 사용할 때 레코드를 선택하기 위한 조건이 아닌 그룹별 통계 조건을 지정하기 위한 SQL문
-- 학생들의 이수학점 평균이 100이상인 학과의 학과번호를 보여주는 SQL문을 만드시오.
select 학과번호 from 학생
group by 학과번호
having avg(이수학점)>=100;
단순한 Select문이 잘 안 되는 경우
-- 수강 테이블에서 'CS100'과 'CS300'을 모두 듣는 학생들의 학번을 구하시오.
select 학번 from 수강
where 과목번호 = 'cs100' and 과목번호 = 'cs300'; (X)
-- 학생 테이블에서 학과번호가 '020'인 학생 모두보다 이수학점이 많은 학생들의 학번을 구하시오.
select 학번 from 학생 where 이수학점 > 120; (X)
-- 학생 테이블에서 학과번호가 '020'인 학생들 중 어느 한 사람보다 이수학점이 많은 학생들의 학번을 구하시오.
select 학번 from 학생 where 이수학점 > 90; (X)
해결방법
- 투플 변수 이용하기
- 투플 변수를 이용하여 하나의 테이블을 마치 두 개의 테이블이 있는 것처럼 두고 카티전 곱을 한 후 필요한 레코드와 속성들을 뽑아낸다.
- 중첩 SQL문 이용하기
- 중첩 SQL문을 이용하여 원하는 값들의 집합을 만들어 그 값들과의 비교를 통해 원하는 레코드와 속성들을 뽑아낸다.
투플 변수를 이용한 Select 문
투플 변수
- SQL문을 실행하는 도중에 투플 하나를 그 때 그 때 담아두기 위한 변수를 투플 변수라고 한다.
사용방법
- 테이블 이름 뒤에 투플 변수 이름을 붙인다.
- 투플 변수의 형태는 테이블 스키마와 같다.
select t1.학번, t1.이름, t2.과목번호
from 학생 t1, 수강 t2
where t1.학번 = t2.학번;
- 즉, 평소에는 테이블 이름이 투플 변수 이름이 된다.
-- 학생 테이블에서 학번이 '9912345'인 학생보다 이수학점이 많은 학생들의 학번과 이름을 검색하시오.
select s1.학번, s1.이름
from 학생 s1, 학생 s2
where s2.학번 = '9912345'
and s1.이수학점 > s2.이수학점;
중첩 Select문
- 하나의 SQL문에 Select문을 두 번 이상 사용하는 것을 중첩 Select문이라고 한다.
사용방법
- 필요한 값들의 집합을 Select문을 이용해서 구한다.
- 이 집합을 조건 식을 만들 때 in, =, some, all 등의 키워드와 같이 사용한다.
select 학번
from 수강
where 과목번호 = 'CS100' and
학번 in
(select 학번
from 수강
where 과목번호 = 'CS300');
select 학번
from 학생
where 이수학점 > some
(select 이수학점
from 학생
where 학과번호 = '020');
select 학번
from 학생
where 이수학점 > All
(select 이수학점
from 학생
where 학과번호 = '020');
과목번호 cs100과 cs300을 모두 듣는 학생의 학번을 구해 보자.
-- intersect 사용 가능
select 학번 from 수강 where 과목번호 = 'cs100'
intersect
select 학번 from 수강 where 과목번호 = 'cs300';
-- 튜플 변수 사용
select s1.학번 from 수강 s1, 수강 s2
where s1.학번 = s2.학번
and s1.과목번호 = 'cs100' and s2.과목번호 = 'cs300';
-- 학번 값 한개가 어떤 집합에 있는가
select 학번 from 수강 where 과목번호 = 'cs100' and
학번 in (select 학번 from 수강 where 과목번호 = 'cs300');
데이터는 변할 수 있으므로 일반화해서 구해야 함.
select 학번 from 학생 where 이수학점 > 120;
-- 방법1) all은 안에 있는거보다 다 커야하고, some은 일부만 커도 됨.
select 학번
from 학생
where 이수학점 > some
(select 이수학점
from 학생
where 학과번호 = '020');
select 학번
from 학생
where 이수학점 > all
(select 이수학점
from 학생
where 학과번호 = '020');
-- 특정 한 학생의 학점보다 큰거는 튜플 변수도 이용 가능
문제
-- 수강신청 데이터베이스에서 학생 테이블에서 전체 학생의 평점 평균을 구해 보자.
select avg(평점) as 평점평균
from 학생;
-- 학생 테이블에서 학과번호별 학생들의 평점 평균을 구해 보자.
select 학과번호, avg(평점) as 평점평균
from 학생
group by 학과번호;
-- 학생 테이블에서 이수학점이 120 이상인 학생 수를 구해 보자.
select count(*) as 마지막학기학생수
from 학생
where 이수학점 >= 120;
-- 수강 테이블에서 각각의 학생이 몇 과목을 수강신청했는지 구해 보자.
select count(*) as 신청한과목수
from 수강
group by 학번;
-- 수강 테이블에서 신청과목 수가 2 이상인 학생들이 몇 과목을 수강신청했는지 구해 보자.
select 학번, count(*) as 신청한과목수
from 수강
group by 학번
having count(*) >= 2;
-- 수강 테이블에서 학생들이 몇 과목을 수강신청했는지 구해 보자.(단 학생 이름이 나오게 하자)
select 학생.이름, count(*) as 신청한과목수
from 학생, 수강
where 학생.학번 = 수강.학번
group by 학생.이름;
-- 수강 테이블에서 학번이 '9912345'인 학생과 학번이 '9955555'인 학생이 모두 수강신청한 과목의 과목번호를 구해 보자.(투플 변수를 이용)
select s1.과목번호
from 수강 s1, 수강 s2
where s1.학번 = '9912345' and s2.학번 = '9955555'
and s1.과목번호 = s2.과목번호;
-- 학생 테이블에서 학번이 ' 9933333 '인 학생보다 평점이 높은 학생의 학번과 이름을 구해 보자.(중첩 쿼리를 이용)
select 학번, 이름
from 학생
where 평점 > (select 학점 from 학생
where 학번 = '9933333');
실습 문제
-- 아래의 설명에 해당하는 테이블을 만들어 보자
테이블 이름 : 서울회원연락처
속성들 : {회원번호, 성명, 주소, 전화번호}, PK : {회원번호}
포함될 레코드 : 회원 테이블에 있는 회원들 중 서울에 사는 회원들의 정보
속성들의 자료 형은 회원 테이블에 있는 동명의 속성들과 같다.
이 테이블은 이미 있는 테이블을 이용하지 말고 Create문과 Insert문을 이용하여 만들자
create table 서울회원연락처 (
회원번호 varchar2(7),
성명 varchar2(20),
주소 varchar2(50),
전화번호 varchar2(20),
primary key (회원번호)
);
insert into 서울회원연락처 values ('T007', '김한수', '서울시 용산구' , '(019)1234-0001');
insert into 서울회원연락처 values ('T009', '이신애', '서울시 송파구', '(011)1234-0003');
insert into 서울회원연락처 values ('T010', '권동하', '서울시 관악구', '(016)1234-0004');
-- 아래의 설명에 해당하는 테이블을 만들어 보자
테이블 이름 : 지방회원연락처
속성들 : {회원번호, 성명, 주소, 전화번호}
포함될 레코드 : 회원 테이블에 있는 회원들 중 서울에 살지 않는 회원들의 정보
속성들의 자료 형은 회원 테이블에 있는 동명의 속성들과 같다.
이 테이블은 이미 있는 회원 테이블을 이용하여 만들자.(Sub query를 이용한 Create문)
create table 지방회원연락처 as
select 회원번호, 성명, 주소, 전화번호 from 회원 where not 주소 like '%서울%';
-- 우리 쇼핑몰에서는 아직 구체적인 상품의 종류는 결정되지 않았으나 앞으로 키보드(분류코드는 4)들도 판매할 계획이다. 이 상황을 SQL로 표현해 보자.
insert into 분류 values (4, '키보드');
-- 우리 쇼핑몰에서는 거래처번호가 4인 거래처로부터 새로운 물건(상품번호가 78이고 상품명은 “삼성 32GB USB 메모리”, 분류코드는 2)을 판매할 것이다. 아직 단가는 결정되지 않았다. 이 상황을 SQL로 표현해 보자.
insert into 상품 values (78, '삼성 32GB USB 메모리', 4, null, 2);
-- 회원들 중 회원번호가 ‘T001’인 회원이 ‘부산시 금정구‘로 이사를 하였다. 이 상황을 SQL로 표현해 보자.
update 회원 set 주소 = '부산시 금정구' where 회원번호 = 'T001';
-- 우리 쇼핑몰에서 판매하는 물건들 중 마우스들의 단가가 10% 인상되었다. 이 상황을 SQL로 표현해 보자.
update 상품 set 단가 = 단가 * 1.1 where 상품명 like '%마우스%';
-- 지금까지 판매하던 물건들 중 상품번호가 8인 상품은 앞으로 판매하지 않을 것이다. 이 상황을 SQL로 표현해 보자.
delete from 주문상세내역 where 상품번호 = 8;
delete from 상품 where 상품번호 = 8;
-- 회원번호가 ‘T004’인 회원이 탈퇴하였다. 이 상황을 SQL로 표현해 보자. 1, 2, 23
회원, 주문, 주문상세내역
delete from 주문상세내역 where 주문번호 in (select 주문번호 from 주문 where 회원번호='T004');
delete from 주문 where 회원번호 = 'T004';
delete from 회원 where 회원번호 = 'T004';
-- 회원들 중 여성이면서 한 번이라도 주문을 한 적이 있는 회원들의 회원번호를 찾는 SQL문을 만들어 보자.
select 회원번호 from 회원 where 성별='여' and 회원번호 in (select 회원번호 from 주문);
select 회원번호 from 회원 where 성별='여'
intersect
select 회원번호 from 주문;
-- 상품들 중 단가가 10000원 이하면서 한 번도 판매되지 않은 상품들의 상품번호를 찾는 SQL문을 만들어 보자.
select 상품번호 from 상품 where 단가<=10000 and 상품번호 not in (select 상품번호 from 주문상세내역);
select 상품번호 from 상품
minus
select 상품번호 from 주문상세내역
intersect
select 상품번호 from 상품 where 단가<=10000;
-- 상품 테이블에서 전체 상품의 단가 평균을 구해 보자.
select avg(단가) as 전체상품단가평균 from 상품;
-- 상품 테이블에서 분류코드에 따른 상품들의 단가 평균을 구해 보자.
select 분류코드, avg(단가) as 분류코드단가평균 from 상품 group by 분류코드;
-- 상품 테이블에서 단가가 10000원 이상인 상품의 개수를 구해 보자.
select count(*) as 만원이상상품개수 from 상품 where 단가>=10000;
-- 주문 테이블에서 회원번호에 따른 주문 횟수를 구해 보자.
select 회원번호, count(*) as 주문횟수 from 주문 group by 회원번호;
-- 주문 테이블에서 세 번 이상 주문한 회원의 회원번호를 구해 보자.
select 회원번호 from 주문 group by 회원번호 having count(*)>=3;
-- 상품, 주문상세내역 테이블에서 상품번호에 따른 주문액 합계를 구해 보자.
select 주문상세내역.상품번호, sum(상품.단가*주문상세내역.수량) as 주문액합계
from 상품, 주문상세내역
where 상품.상품번호=주문상세내역.상품번호
group by 주문상세내역.상품번호;
-- 상품, 주문상세내역 테이블에서 상품번호에 따른 주문액 합계가 100,000원 이상인 상품의 상품번호를 구해 보자.
select 주문상세내역.상품번호, sum(상품.단가*주문상세내역.수량) as 주문액합계
from 상품, 주문상세내역
where 상품.상품번호=주문상세내역.상품번호
group by 주문상세내역.상품번호
having sum(상품.단가*주문상세내역.수량)>=100000;
-- 주문, 주문상세내역, 상품 테이블에서 주문번호에 따른 주문액 합계를 구해 보자.
select 주문상세내역.주문번호, sum(상품.단가*주문상세내역.수량) as 주문액합계
from 주문, 주문상세내역, 상품
where 주문.주문번호=주문상세내역.주문번호
and 상품.상품번호=주문상세내역.상품번호
group by 주문상세내역.주문번호;
-- 주문 테이블에서 2017년 1월 2일과 1월 3일에 모두 주문한 회원의 회원번호를 구하시오.
-- intersect를 이용하여 구하시오.
select 회원번호 from 주문 where 주문일='2017-01-02'
intersect
select 회원번호 from 주문 where 주문일='2017-01-03';
-- 중첩 쿼리문을 이용하여 구하시오.
select 회원번호 from 주문
where 주문일='2017-01-02'
and 회원번호 in (select 회원번호 from 주문 where 주문일='2017-01-03');
-- 상품 테이블에서 분류코드가 1인 상품들의 모든 단가보다 단가가 큰 상품의 상품번호와 상품명을 구하시오.
-- 중첩 쿼리문을 이용하여 구하시오.
select 상품번호, 상품명 from 상품
where 단가 > all (select 단가 from 상품 where 분류코드=1);
-- 상품 테이블에서 상품번호가 14인 상품의 단가보다 단가가 큰 상품의 상품번호와 상품명을 구하시오.
-- 투플 변수를 이용하여 구하시오.
select P1.상품번호, P1.상품명
from 상품 P1, 상품 P2
where P2.상품번호=14
and P1.단가>P2.단가;
'CS > 인터넷DB응용' 카테고리의 다른 글
[인터넷DB응용] PL-SQL - 2 (0) | 2023.04.17 |
---|---|
[인터넷DB응용] PL-SQL - 1 (0) | 2023.04.16 |
[인터넷DB응용] SQL 활용 - 3 (0) | 2023.04.14 |
[인터넷DB응용] SQL 활용 - 1 (0) | 2023.04.11 |
[인터넷DB응용] 데이터베이스 기본 이론 (0) | 2023.04.10 |