'공부/데이터베이스'에 해당되는 글 20건

반응형

병행 수행

- 여러 사용자가 DB를 동시 공유할 수 있게 여러개의 트랜잭션을 동시에 수행하는 것

- 여러 트랜잭션이 차례로 번갈아 수행되는 인터리빙 방식으로 진행

(단위 시간에 많은 트랜잭션을 처리하기 위해)

(트랜잭션 제각각 처리 시간이 다르므로, 처리시간이 긴 연산 수행 동안 다른 연산 수행)

 

병행제어

- 병행 수행시, 같은 데이터에 접근하여 연산을 실행해도 문제가 발생하지 않고 정확한 수행 결과를 얻을 수 있게 트랜잭션 수행을 제어하는 것.

- 정확한 수행 결과가 아닌 경우가 발생하지 않게 병행제어를 잘 해야한다.

 

 

병행 수행 시 발생할 수 있는 문제점

1. 갱신 분실

- 하나의 트랜잭션이 수행한 데이터변경 연산의 결과를 다른 트랜잭션이 덮어서 변경연산 무효화됨

- 여러 트랜잭션이 동시에 수행되더라도 순차적으로 수행한것과 같은 결과값을 얻을 수 있어야된다.

=> T1에 대해 갱신 분실이 발생한다.

 

트랜잭션을 순차적으로 수행하면 해결된다.

 

 

2. 모순성

- 하나의 트랜잭션이 여러 개 데이터 변경 연산을 실행할때, 일관성 없는 상태의 데이터베이스에서 데이터를 가져와 연산 => 모순된 결과가 발생

T1이 X, Y를 다른 상태의 데이터베이스에서 가져와 

트랜잭션 T1의 결과가 X= 4000, Y = 4000이 아닌 X=2000, Y=2500의 잘못된 결과가 나온다.

T1이 완료된후 T2가 실행되면 모순성 문제가 발생하지 않는다.

 

3. 연쇄복귀

- 트랜잭션이 완료되기전, 장애가 발생하여 rollback연산을 수행 => 장애 발생 전에 트랜잭션이 변경한 데이터를 가져가 변경연산을 실행한 다른 트랜잭션도 연쇄적으로 rollback연산을 해야함

==> 장애로 잘못된 결과가 나오고 그 잘못된 결과를 가져가 다른 트랜잭션이 연산을 수행했으므로

(T1 -> 결과(문제발생) -> T2 -> 결과(문제발생!, 잘못된 결과로 연산하였으므로)

 

T2는 T1이 변경한 X를 가져가 연산을 수행한다.

T1 트랜잭션 완료 전 장애가 발생한다.

T1을 rollback해야하지만, T2는 연산이 이미 끝나 rollback이 불가하다.

순차적으로 수행 (T1완료후  -> T2수행)하면 연쇄 복귀 문제가 발생하지 않는다.

 

 

트랜잭션 스케줄

1. 직렬 스케줄 => 인터리빙이 아닌, 각 트랜잭션별로 연산을 순차적으로 실행 => 시간이 길어짐

2. 비직렬 스케줄 => 인터리빙 방식으로 트랜잭션 병행해서 수행 => 병행성 문제 발생

3. 직렬 가능 스케줄 => 직렬스케줄처럼 정확한 결과를 생성하는 비직렬 스케줄 => 시간을 줄이고 병행성 문제 해결

 

1. 직렬 스케줄

- 다른 트랜잭션의 방해를 받지 않고 독립적으로 수행 => 항상 모순 없는 결과

- 병행 수행이 아님 => 시간이 오래걸림

- 다양한 직렬 스케줄을 만들 수 있음

 

T1 -> T2

T2 -> T1

 

2. 비직렬 스케줄

- 트랜잭션이 번갈아 연산 실행 => 하나의 트랜잭션 완료전 다른 트랜잭션 연산 실행가능

- 갱신분실, 모순성, 연쇄복귀 문제 발생하여 결과의 정확성 보장 X

- 다양한 비직렬 스케줄 생성가능 (그중엔 잘못된 결과를 생성하기도함)

 

비직렬 스케줄이지만 병행 수행에 성공하여 정확한 트랜잭션 수행 결과를 생성한다. => 직렬가능 스케줄

 

병생 수행에 실패하여 잘못된 결과를 생성한다.

 

 

 

 

3. 직렬 가능 스케줄

- 비직렬 스케줄 중에서 수행 결과가 동일한 직렬 스케줄이 있는 것.

- 인터리빙 방식으로 병행수행하면서 정확한 결과 얻음

- 직렬 가능 스케줄인지 판단한는것은 복잡한 작업

- 따라서 직렬가능성을 보장하는 병행제어 기법 사용 

 

 

 

병행 제어 기법

- 병행 수행하면서 직렬 가능성도 보장

- 모든 트랜잭션이 준수하면 직렬가능성이 보장되는 rule 정의

- lock 기법이 있음

 

lock기법 - 상호배제

- 병행 수행되는 트랜잭션들이 같은 데이터에 동시에 접근하지 못하게 lock/unlock연산

lock - 트랜잭션이 데이터에 대한 독점권 요청

unlock - 트랜잭션이 데이터에 대한 독점권 반환

 

- 데이터에 접근하기 전 lock하여 독점권을 획득 (read/write 전 lock)

- 다른 트랜잭션에 의해 이미 lock이 걸린 데이터는 lock 불가& 실행 불가

- 연산 수행 끝나면 unlock

 

lock 단위가 커지면 병행성은 낮아지지만 제어가 쉬워지고

단위가 작아지면 제어가 어렵지만 병행성은 높아진다.

 

lock 효율 향상 => 동시성이 높아짐

공용 lock => read만 가능

- read연산 수행가능 ,write 불가 

- 다른 트랜잭션도 동시에 공용 lock 가능

- 데이터 사용권을 여러 트랜잭션이 함께 가지는 것 가능

 

전용 lock => write하기 위해

- read/write 둘다 가능

- 다른 트랜잭션은 어떠한 lock 연산도 실행 불가

- 데이터에 대한 독점권 가짐

 

T1이 X에 대해 빨리 unlock을 해버려 T2가 일관성 없는 데이터에 접근하여 잘못된 결과가 나온다.

(T1이 끝날때까지 lock을 해야한다.)

 

2단계 lock rule = 축소, 확장

- 위와 같은 기본 lock rule의 문제 해결

- 직렬 가능성 보장 위해 lock/unlock연산 수행 시점에대한 새로운 rule 추가

- 트랜 잭션이 처음수행되면 확장단계 => lock만 가능 (lock을 검)

- unlock 연산을 실행하면, 축소단계 => unlock만 가능

- 트랜잭션은 첫번째 unlock 연산전, 필요한 lock 연산을 실행해야한다.

 

하지만 이러한 방법도 

T1 -> X (lock)  ====> Y가 unlock 되길 기다림

T2 -> Y (lock) =====> X가 unlock 되길 기다림

과 같은 경우 데드락이 발생 할 수 있다.

따라서 교착 상태가 발생되지 않게 예방하거나 빨리 탐지하여 조치를 해야한다.

 

 

 

 

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 회복  (0) 2021.06.03
관계 대수  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
블로그 이미지

아상관없어

,
반응형

병행제어 : 수많은 사람들이 동시에 데이터베이스를 이용하는데 문제가 발생하지 않게 제어해주어야한다.

 

트랜젝션

- 하나의 작업을 수행하는데 필요한 데이터베이스 연산을 모은것.

- 작업 수행에 필요한 SQL문 집합

- 논리적 작업단위

- 장애발생시, 복구나 병행제어 작업을 위한 중요한 단위로 사용

- DB의 무결성과 일관성을 보장하기 위해서 작업 수행에 필요한 연산들을 하나의 트랜잭션으로 제대로 정의하고 관리해야함.

ex 1)

1번 작업과 2번 작업이 하나의 트랜잭션이다.

처리 순서는 중요하지 않지만, 두개의 update 명령이 정상적으로 실행되어야한다.

 

ex 2)

insert와 update 모두 정상적으로 실행되어야 상품주문 트랜잭션이 성공적으로 수행된다.

 

 

트랜잭션 특성

1. 원자성 => 회복기능

- all or nothing

- 트랜잭션의 연산들이 모두 정상적으로 실행 or 하나도 실행 X

- 트랜잭션 수행중 장애가 발생되면? => 실행한 연산을 모두 취소하고 DB를 트랜잭션 작업 전으로 복구

- 따라서 원자성 보장을 위해 회복 기능이 필요하다.

ex)

DB = A: 10000, B : 0

-계좌이체 트랜잭션-

(1) A계좌에서 5000원 인출

(2) B계좌에 5000원 입금

DB = A: 5000, B: 5000

 

1,2번 작업 중 장애가 발생하면 실행한 작업을 취소하고

DB = A: 10000, B : 0

상태로 되돌린다.

 

2. 일관성 => 병행 제어

- 트랜잭션이 성공적으로 수행된 후에도 DB가 일관된 상태를 유지해야한다.

ex)

DB = A: 10000, B : 0  ==> 합계 10000

-계좌이체 트랜잭션-

(1) A계좌에서 5000원 인출

(2) B계좌에 5000원 입금

DB = A: 5000, B: 5000  ==> 합계 10000

 

 

 

3. 격리성 => 병행 제어

- 수행 중인 트랜잭션이 완료될때까지, 다른 트랜잭션이 중간 연산 결과에 접근 불가

- 다른 트랜잭션과 연결 X, 독립됨

- 여러 트랜잭션이 동시에 수행되더라도, 순서대로 하나씩 수행되는 것처럼 정확하고 일관된 결과를 얻게 제어해야함

- 트랜잭션 서로 간섭 X

 

DB = A: 10000, B : 0

-계좌이체 트랜잭션-

(1) A계좌에서 5000원 인출

(2) B계좌에 5000원 입금

DB = A: 5000, B: 5000

 

여기서 B계좌에 1000원을 입금하는 다른 트랜잭션이 동시에 수행되어 (1)작업 후 수행되면

계좌입금 트랜잭션은 

-계좌입금 트랜잭션-

DB = A: 5000, B : 0

(1) B 계좌에 1000원 입금

DB = A: 5000, B : 1000

이 되어 두 트랜잭션이 완료되면

DB = A: 5000, B: 5000

DB = A: 5000, B : 1000

B의 계좌 잔액이 일치하지 않게 된다.

 

이러한 문제가 발생한 원인은 두 트랜잭션이 간섭을 일으키기 때문이다. 

따라서 계좌이체 트랜잭션이 끝날때 까지 기다린후, 계좌 입금 트랜잭션을 수행하면 같은 정보를 update하는 충돌이 발생하지 않는다.

즉, 간섭(충돌)이 되는 작업은 기다리고 아니면 동시수행한다.

 

 

 

4. 지속성 => 회복기능

- 트랜잭션이 성공적으로 완료된 후, 데이터베이스에 반영한 수행결과는 영구적이여야 함.

- 트랜잭션을 성공했으면 결과는 어떤일이 일어나더라도 유지되야한다.

(만약 트랜잭션을 성공했는데 시스템 다운으로 데이터가 날라가 결과에 데이터가 없으면 안된다.)

- 지속성의 보장을 위해선 장애 발생시 회복기능이 필요하다. (다시 복구)

 

 

 

트랜 잭션의 주요연산

1. commit - 트랜잭션이 성공적으로 수행되었음을 선언 (작업 완료)

=> 트랜잭션의 수행 결과가 데이터베이스에 반영되고 일관된 상태를 지속적으로 유지

2. rollback - 트랜잭션을 수행하는데 실패했음 선언 (작업 취소)

=> 지금까지 실행한 연산 결과를 취소하고 트랜잭션 수행 전의 데이터베이스로 상태 되돌림

 

 

트랜 잭션 상태

활동(수행중) -> 실패 -> rollback -> 철회

                 -> 부분완료 -> commit -> 완료

                 -> 부분완료 -> 실패 -> rollback -> 철회

 

활동

- 트랜잭션 수행중

 

부분 완료

- 트랜잭션의 마지막 연산이 실행을 끝낸 직후

 

완료

- 트랜잭션이 성공적으로 완료되어 commit 연산 실행한 상태, 결과를 DB에 반영, DB가 새로운 일관된 상태가 되고 트랜잭션 종료

 

실패

- 장애가 발생하여 트랜잭션 수행 중단된 상태

 

철회

- 트랜잭션 수행실패로 rollback 연산 실행한 상태,

- 지금까지 실행한 트랜잭션 연산을 모두 취소 후 트랜잭션 수행 전으로 DB되돌리고 트랜잭션 종료

- 철회 상태로 종료된 트랜잭션은 다시 수행되거나 폐기됨(상황에 따라)

 

장애 

휘발성 저장장치(소멸성 ) : 장애가 발생하면 저장된 데이터 손실

비휘발성 저장장치(비소멸성) : 장애가 발생해도 저장된 데이터 손실X, 저장장치 자체에 이상이 발생하면 데이터 손실

안정 저장장치 : 비휘발성 저장장치 이용, 데이터 복사본 여러개, 어떤 장애가 발생되도 데이터 손실X, 데이터 영구적 저장

 

트랜잭션 수행을 위해 필요한 데이터 이동 연산

응용프로그램 <-(read) - 메인메모리 <-(input) - 디스크

응용프로그램 ->(write) - 메인메모리 - (output)-> 디스크

read/write에 비해 input, output은 느리다.

트랜잭션에 read/write, input/output 연산이 포함된다.

 * 메인 메모리 데이터 베이스 = 디스크에 있다가 실행 시점에 전부 메인메모리로 가져와 사용한다. (규모가 작고 빠른 R/W시 사용한다.) (주로 read인 경우 - select)

 

디스크와 메인메모리 간의 데이터 이동연산은 block단위로 수행된다.(한번 읽는 시간이 느리므로 block 단위로 읽어옴)

 

 

회복(복구)를 위해 데이터베이스 복사본을 만드는 방법 => 데이터 중복!

덤프(dump) = 데이터베이스 전체를 다른 저장장치에 주기적으로 복사

로그(log) = 데이터베이스에서 변경 연산이 실행될 때마다, 데이터를 변경하기 이전값이후값을 별도의 파일에 기록

ex)

5일마다 backup을 한다면, 원본과 복사본 간에 시간차가 생긴다.

DB -(5일 시간차)-> 백업DB 

따라서, log를 사용 =>  5일전 복사본에 log로 변한 것을 적용하면 현재 DB상태가 된다.

 

 

회복(복구)를 위한 기본 연산

redo(재실행) = 가장 최근에 저장한 DB복사본을 가져온 뒤, log를 이용해서 복사본이 생성된 후의 모든 변경 연산을 재실행하여 장애 발생전의 DB상태로 복구

undo(취소) = log를 이용하여 실행된 모든 변경 연산을 취소하여 DB를 원래 상태로 복구(변경중이었거나, 변경된 내용만 신뢰성을 잃은 경우)

* log : 데이터를 변경하기 이전값과 변경한 후의 값을 기록한 파일, 레코드 단위로 트랜잭션 수행과 함께 기록

 

 

 

DB 회복(복구) 기법

- 로그 회복기법(즉시 갱신, 지연갱신 회복기법)

- 검사 시점 회복기법

- 미디어 회복기법

 

1. 로그 회복 - 즉시갱신 회복기법

- 트랜잭션 수행 중 데이터 변경 연산 결과를 DB에 즉시 반영

- 장애 발생에 대비하기 위해, 데이터 변경에 관한 내용을 log에 기록

- 데이터 변경 연산이 실행되면, log파일에 log 레코드를 기록하고 DB에 변경 연산 반영

- 장애 발생 시점에 따라 redo, undo 연산을 하여 DB 복구

바로 바로 반영한다.

 

1) 트랜 잭션이 완료되기 전에 장애가 발생

=> <T1, start>레코드는 있지만 commit레코드는 없다, 따라서 undo 연산

2) 트랜 잭션 완료 후 장애 발생

=> start, commit 로그 레코드 둘다 존재(정상적으로 실행되었다 판단), 따라서 redo 연산

1 => 일부이므로 undo 연산

2 => T2는 일부만 시행했으므로 undo, T1은 commit했으므로 redo

 

2. 로그 회복기법 - 지연갱신 회복

- 트랜 잭션 수행중 데이터 변경 연산 결과를 로그에만 기록

- 트랜 잭션이 부분완료된 후 로그에 기록된 내용을 DB에 한번에 반영 (commit을 만나면 DB에 반영)

- 트랜 잭션 수행중, 장애 발생하면 로그기록을 버리면 DB가 원래 상태 유지하게 됨 (DB에 반영은 나중에 하므로)

- log만 삭제하면 되므로 undo 연산은 필요없고, redo 연산만 사용한다.

- 로그 레코드에는 변경 이후 값만 기록하면 됨.

 

1) 트랜 잭션이 완료되기 전에 장애가 발생

=> <T1, start>레코드는 있지만 commit레코드는 없다, 따라서 기록된 log 버림

2) 트랜 잭션 완료 후 장애 발생

=> start, commit 로그 레코드 둘다 존재(정상적으로 실행되었다 판단) => 데이터베이스에 반영, 따라서 redo 연산

 

 

3. 검사시점 회복 기법

- 로그 기록 이용

- 일정 시간 간격으로 checkpoint생성

- checkpoint 시점이 되면 모든 log 레코드를 log에 기록 => 데이터 변경 내용을 안정저장창지에 기록 => 검사시점을 표시하는 <checkpoint L> 로그 레코드를 로그 파일에 기록

- 백업본 + log로 복구

- 백업후 시행한 것 모두 redo or undo 하여야한다 => 양이 많을 수 있음

- 따라서 일정 시간 마다 안정저장장치에 변경 내용 저장

- 마지막 check point 이후 작업만 처리한다. => 가장 최근 검사 시점 이후의 트랜잭션에만 회복 작업 수행(즉시 갱신 or 지연 갱신 복구)

- 백업후 시행한 것 모두 redo or undo 하여야한다 => log 전체를 회복기법 적용하는 것 보다 효율성이 좋음

- 검사 시점으로 작업 범위가 정해지므로 불필요한 회복 작업이 없어서 시간 단축

 

 

4. 미디어 회복 기법

- 디스크에 발생할 수 있는 장애에 대비

- 덤프(복사본) 이용 => 전체 DB내용을 일정 주기마다 다른 안전한 저장장치에 복사

- 디스크 장애 발생시 => 가장 최근에 복사해둔 덤프를 이용하여 장애 발생 이전의 DB 상태로 복구, 필요에따라 redo연산 수행

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 병행제어  (0) 2021.06.04
관계 대수  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
블로그 이미지

아상관없어

,
반응형

관계 데이터 연산 

- 관계형 모델에서 제공하는 데이터를 다루기 위한 방법

- 원하는 데이터를 얻기위해 릴레이션에 필요한 처리 요구를 수행하는 것

- 관계대수: 원하는 결과를 얻기 위해 데이터의 처리과정을 순서대로 기술

- 관계해석: 원하는 결과를 얻기 위해 처리를 원하는 데이터가 무엇인지만 기술

 

관계대수와 관계해석

데이터 언어의 유용성을 검증하는 기준

=> 언어가 적합한지(관계대수/해석으로 할 수 있는 것을 제시한 언어 문법체계로 다 구현가능한지?)

관계 대수나 관계 해석으로 기술할 수 있는 모든 질의를 기술할 수 있는 데이터 언어 = 관계적으로 완전

 

관계 해석

어떻게 검색(X)

무엇을 검색(O)

무엇을 검색할것인가만 기술하는 선언적 표현법을 사용하는 비절차적 질의어

SQL등 많은 상업용 관계언어들이 관계해석에 기반을 두고있음

 

 

관계대수

- 원하는 결과를 얻기 위해 릴레이션의 처리 과정을 순서대로 기술하는 언어(절차 언어)

- 릴레이션을 처리하는 연산자들의 모임

- 폐쇄 특성이 존재(닫힌 성질) => 피 연산자도 릴레이션이고, 연산의 결과도 릴레이션임, input형태 = output형태 동일

 

관계대수와 관계해석 차이

- 관계해석 : 하나의 선언적, 해석식으로 검색질의를 명시, 비절차적 언어

- 관계대수 : 연산들을 순차적으로 사용하므로 절차적인 성질을 가짐

두 표현의 표현력은 동등

 

 

관계대수 연산자

1. 일반 집합 연산자

합집합 => 교환적, 결합적 특징, 차수는 릴레이션들의 차수와 동일, 카디널리티(행의 수)는 두 릴레이션의 카디널리티를 더한 것과 같거나 작음

교집합 => 교환적, 결합적 특징, 차수(컬럼수)는 두 릴레이션의 차수와 동일, 카디널리티(행 수)는 두 릴레이션 중 어떤 카디널리티보다 크지 않다.

차집합 (R-S) => R에는 존재하지만,  S에는 존재하지 않느 투플로 결과 릴레이션 구성, 차수는 R,S의 차수와 같음, 카디널리티는 R의 카디널리티와 같거나 적음, 교환적, 결합적 특징이 없음

 

카티션 프로덕트 => 교환적, 결합적 특징, R에 속한 투플과 S에 속한 투플을 모두 연결함. 차수는 R,S의 차수를 합한것과 동일, 카티널리티는 R과 S의 카디널리티를 곱한것과 같음

 

- 피연산자가 2개 필요하다

- 합집합, 교집합, 차집합은 피연산자인 두 릴레이션이 합병가능해야한다.

(합병가능 : 두 릴레이션의 차수(컬럼의 수)가 동일, 두 릴레이션에서 서로 대응되는 속성(칼럼)의 도메인이 같아야함(자료형이 동일해야)

 

순수 관계 연산자 => 릴레이션의 구조와 특성을 이용

셀렉트 σ(조건)(R) => 릴레이션 R에서 조건을 만족하는 투플들(행)을 반환 (행단위로 반환)

"릴레이션 where 조건식" 과 동일

비교연산자, 논리 연산자(∧, ∨, ¬(and, or, not))를 이용하여 작성

ex) 고객 릴레이션에서 등급이 gold인 투플을 검색하시오

σ(등급 = 'gold')(고객) = 고객 where 등급 = 'gold'

 

프로젝트  π(속성 리스트)(R) => 릴레이션 R에서 주어진 속성들의 값으로만 구성된 투플을 반환 (열단위로 반환)

ex) 고객이름, 등급, 적립금을 검색

π(고객이름, 등급, 적립금)(고객)

 

조인 R⋈S(자연조인) => 공통 속성을 이용하여 R,S의 투플들을 연결함

고객 ⋈ 주문

외래키는 지정이 되지 않아도 조인시 문제가 없지만 무결성 문제가 발생한다.

공통속성인 (고객.고객아이디), (주문.주문고객)은 한번만 나타난다. => 고객 아이디만 나타남

차수(속성)의 개수 = 두차수의 합 - 공통 속성의 개수

 

세타조인 R⋈(JOIN 조건)S => 자연조인에 비해 일반화된 조인, 

주어진 조인조건을 만족하는 두 릴레이션의 모든 투플을 연결하여 생성된 새로운 투플이 결과 릴레이션

결과 릴레이션의 차수는 두 릴레이션의 차수를 더한것

ex) 

고객⋈(고객아이디=주문고객)S

자연조인과 다르게 공통 속성이 둘다 표시된다.

 

디비전 R ÷ S => 릴레이션 S의 모든 투플과 관련 있는 릴레이션 R의 투플 반환

R이 S의 모든 속성을 포함하고 있어야 연산이 가능하다

고객 릴레이션에서 gold 등급을 가진 투플을 고름. 나누기에서 몫과 유사

 

 

 

외부 조인 (R ⋈+ S)=> 자연조인 연산에서 제외되는 투플도 결과 릴레이션에 포함시킴, 즉 두 릴레이션에 잇는 모든 투플을 결과 릴레이션에 포함 시킴

 

 

 

관계대수 예시)

1. 모든 부서의 이름과 지역명을 보이시오

2. 모든 사원의 이름과 담당업무를 보이시오

3. 담당업무가 ‘salesman’ 인 사원의 이름, 입사일자를 보이시오

4. 입사일자가 ‘1999-02-31’ 이후인 사원의 사원번호, 이름, 입사일자를 보이시오

5. 모든 사원의 이름과 부서명을 보이시오

6. 급여액(연봉)1000 이상인 사원의 이름, 급여액, 부서명을 보이시오

7. 입사일자가 ‘1999-02-31’ 이후인 사원의 사원번호, 이름, 부서명을 보이시오.

8. ‘Dalls’ 에 근무하는 사원의 이름, 급여액을 보이시오

9. 입사일자가 ‘1998-01-01’ 이전인 사원중 급여액이 1000 미만인 사원의 사원번호, 이름, 부서명을 보이시오.

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 병행제어  (0) 2021.06.04
회복과 병행제어 - 회복  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
블로그 이미지

아상관없어

,
반응형

Mysql my_db 와 연동하여 다음 내용을 실행하는 python 프로그램 

- 사원번호가 7521인 사원의 이름을 출력한다

- 이름이 SCOTT 인 사원의 부서이름을 출력한다

- 담당업무가 SALESMAN 인 모든사원의 이름을 출력한다.

- 모든 부서의 이름을 출력한다.

 

#mysql - python connection test

import pymysql #mysql과 연동하기 위해

#필요한 기본 DB 정보
host = "localhost"
user = "root"
pw = "password"
db = "my_db"

#DB에 접속
conn = pymysql.connect(host= host, user = user, password = pw, db = db)

#사용할 sql문
sql1 = "SELECT ename FROM emp WHERE empno=7521"
sql2 = "SELECT dname FROM emp, dept WHERE dept.deptno=emp.deptno and ename='scott'"
sql3 = "SELECT ename FROM emp WHERE job='salesman'"
sql4 = "SELECT dname FROM dept"

querys = [sql1, sql2, sql3, sql4]

for sql in querys:
    print(sql)
    
    # sql문 실행/데이터 받기
    curs = conn.cursor() #sql 실행시 결과를 담고 있는 버퍼를 정렬
    curs.execute(sql)	#앞의 sql문 실행 
    row = curs.fetchone() #sql실행결과 모두 가져오기, fetchall 모든 행 가져옴, fetchone은 하나의 행만 가져옴
    while(row):
        print(row)
        row	= curs.fetchone()	
        
    print("==========================================================")
    
#db 접속 종료
curs.close()
conn.close()

 

 

 

Mysql world 데이터베이스와 연동하여 다음과 같이 국가명을 입력하면 해당 국가의 정보를 출력하는 윈도우 프로그램

- 매치되는 국가가 없으면 모든 항목에 공백 출력

import sys
import pymysql
from PyQt5.QtWidgets import *

def connectDB():
    #필요한 db 정보
    host = "localhost"
    user = "root"
    pw = "Changmin97"
    db = "world"
    
    #db 접속
    conn = pymysql.connect(host=host, user =user, password =pw, db =db)
    return(conn)  #connection  리턴

def disconnectDB(conn):
    conn.close()
    
    

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    
    # UI 디자인 함수
       def initUI(self):
        #QLable 문자열 출력
        label1 = QLabel('Country name')
        label2 = QLabel('Continent')
        label3 = QLabel('Population')
        label4 = QLabel('GNP')
        label5 = QLabel('Captial city')
        label6 = QLabel('Language')
    
    

        #text_Country_name
        self.text_Country_name = QTextEdit()
        self.text_Country_name.setFixedWidth(200)
        self.text_Country_name.setFixedHeight(30)
    
    
        #버튼 생성, 버튼 클릭시 btn_1_clicked 실행
        btn_1 = QPushButton('Query')
        btn_1.clicked.connect(self.btn_1_clicked)
    
        #text_Continent
        self.text_Continent = QTextEdit()
        self.text_Continent.setFixedWidth(200)
        self.text_Continent.setFixedHeight(30)
    
        #text_Population
        self.text_Population = QTextEdit()
        self.text_Population.setFixedWidth(200)
        self.text_Population.setFixedHeight(30)
    
        #text_GNP
        self.text_GNP = QTextEdit()
        self.text_GNP.setFixedWidth(200)
        self.text_GNP.setFixedHeight(30)
        
        #text_Captial_city
        self.text_Captial_city = QTextEdit()
        self.text_Captial_city.setFixedWidth(200)
        self.text_Captial_city.setFixedHeight(30)
        
        #text_Language
        self.text_Language = QTextEdit()
        self.text_Language.setFixedWidth(200)
        self.text_Language.setFixedHeight(30)
        
        
        
    
        #화면 배치, grid를 만들어 배치
        gbox = QGridLayout()
    
        gbox.addWidget(label1,0,0)
        gbox.addWidget(self.text_Country_name, 0, 1)
            
        gbox.addWidget(btn_1, 0, 2)
            
        gbox.addWidget(label2,1,0)
        gbox.addWidget(self.text_Continent, 1, 1)
            
        gbox.addWidget(label3,2,0)
        gbox.addWidget(self.text_Population, 2, 1)
        
        gbox.addWidget(label4,3,0)
        gbox.addWidget(self.text_GNP, 3, 1)
        
        gbox.addWidget(label5,4,0)
        gbox.addWidget(self.text_Captial_city, 4, 1)
        
        gbox.addWidget(label6,5,0)
        gbox.addWidget(self.text_Language, 5, 1)
    

        self.setLayout(gbox)
        self.setWindowTitle('Country Info')
        self.setGeometry(300, 300, 480,250) #창뜨는 위치, 크기
        self.show()
        
        
    #버튼 클릭 처리
    def btn_1_clicked(self):
    
        #사용자가 입력한 값 받아서 empno 저장
        Country_name = self.text_Country_name.toPlainText()
            
        sql = "SELECT country.name, continent, country.population, gnp, city.name, language \
                From country, city, countrylanguage\
                where country.code = city.countrycode \
                    and country.code = countrylanguage.countrycode\
                    and country.capital=city.id\
                    and IsOfficial = 'T' \
                    and country.name ="+"'"+Country_name+"'"
        #ex) ename '"+ename+"'" =>문자일 경우 따옴표 주의!
        conn = connectDB()
        curs = conn.cursor()
        curs.execute(sql)
            
        result = curs.fetchone() # sql 실행 결과 가져오기

        if result:    
            self.text_Country_name.setText(result[0])
            self.text_Continent.setText(result[1])
            self.text_Population.setText(str(result[2]))
            self.text_GNP.setText(str(result[3]))
            self.text_Captial_city.setText(result[4])
            self.text_Language.setText(result[5])
        else:
            self.text_Country_name.setText("") #매치되는 국가가 없으면 모든 항목에 공백 출력
            
            
        curs.close()
        disconnect(conn)
            
#END Class


#프로그램 실행, class를 생성하고 실행
if(__name__ == '__main__'):
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())            
    
        

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

회복과 병행제어 - 회복  (0) 2021.06.03
관계 대수  (0) 2021.06.03
index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
블로그 이미지

아상관없어

,

index

공부/데이터베이스 2021. 6. 2. 23:50
반응형

ex) select ename from emp where empid = 7934;

위 명령을 수행할때

1. 순차적으로 검색한다.

=> 요청이 많을 경우 처리시간이 오래 걸리게 된다.

 

2. 이진 검색 (데이터가 정렬되어 있는 경우)

데이터가 갱신 될때마다 정렬작업을 하여야하므로 비용부담이 크다.

 

3. index 이용 (index = keyword + address)

index는 해당 값의 주소를 가리킨다. 

그리고 index는 항상 sorting된 상태이다.(실제 데이터는 정렬되어 있을수도 있고 아닐수도 있다.)

index가 있는 column의 값을 기준으로 조회하면 빨라진다.

 

대부분의 DBMS는 기본키, 외래키에 대해 자동으로 index를 설정한다.

=> 테이블 생성시 기본키를 생성하면 자동으로 인덱스생성

외래키 컬럼에 대해서도 인덱스가 생김

기본키가 되었단 말은 검색의 기준으로 많이 선택되니 인덱스를 붙이는 것이 속도를 빠르게 할 수 있음

외래키도 테이블과 테이블을 조인하여야되는데, 매치되는 항목을 찾아야하므로 인덱스를 걸어주어 join연산을 빠르게 해줌

기본키 - empno

자기자신참조 - mgr

외래키 - deptno

에 대해 자동으로 인덱스가 생성됨

=> 인덱스가 없는 column을 기준으로 검색시 속도가 느림

따라서 검색 기준이 될만한 column들은 인덱스를 생성하는 것이 좋음

 

만약 모든  column에 index를 생성하면??

인덱스는 항상 정렬된 상태를 유지해야하므로, overhead가 커진다. 따라서 최소한의 index를 유지하는 것이 좋다.

 

 

SQL문으로 index생성하기

create index idx_job on emp (job);
show index on emp;

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

관계 대수  (0) 2021.06.03
파이썬 연동 예제  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
저장 함수 예제  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

DBMS의 목적 중 하나는 데이터 베이스에 저장된 정보를 안전하게 보호하는 것이다.

이를 수행하기 위한 수단으로

추가 로그인

암호화 => 민감한 정보

사용자 관리 => 등록된 계정만

권한 관리

가 있다.

 

사용자 관리

사용자가 DB를 이용하기 위해선 계정이 필요함

사용자가 DBMS에 로그인하면 DBMS는 등록된 사용자인지 검사함

따라서 이를 위해 사전에 계정생성이 필요하다.

 

root

최고권한을 가진 사용자 계정으로 데이터베이스 및 DBMS에 대한 모든 권한을 가진다.

따라서 비밀번호가 노출되면 위험하고 일반 사용자에게 root권한을 주는 것은 위험하다.

그러므로 일반 사용자들은 별도의 계정을 만들어 사용하도록 해야한다.

 

사용자계정 생성시

localhost => DBMS 서버에 직접 접근 -> 원격접속 불가

% => DBMS에 원격 접속 ->직접접근 불가

 

서버에 직접 접속, 원격접속 둘다 하려면 같은이름의 local, remote계정 두가지 많들어야한다. 

 

권한은

1. 모든 DB

2. 패턴에 매칭되는 DB(이름으로 검색), 선택한 DB

에 접근할 수 있는 권한을 줄 수 있고,

select, insert, update, delete, execute, show view, create, alert, index, drop..... 와 같은 권한을 줄 수 있다

 

 

Mysql workbench는 DB단위로 권한을 부여하고 회수한다. => 세부적으로 되지 않는다.

따라서 sql 명령문 (grant, revoke)를 이용하여 테이블 단위로 권한을 부여하고 회수할 수 있다.

 

GRANT select ON my_db.emp TO user_1@localhost;
GRANT select, insert, update ON my_db.dept TO user_1@localhost;

 

 

root 사용자일 경우 sql문을 사용하여 사용자를 생성하고 권한부여, 회수가 가능하다.

localhost 사용자의 경우'

create user user_2@localhost identifited by '4321';

 

원격접속 사용자의 경우

create user 'user_2'@'%' identified by '4321';

 

생성된 사용자 확인

SELECT * from mysql.user;

mysql => system 카탈로그 정보가 있는 데이터 베이스

user => user테이블에 사용자 정보가 저장

 

 

권한의 부여

my_db에 대한 모든 권한 부여
grant all privileges on my_db.* to user_2@localhost;


일부 권한 부여
grant select, insert on my_db.* to user_1@localhost;


테이블에 대한 모든 권한 부여
grant all privilleges on my_db.emp to user_1@localhost;


테이블에 대한 일부 권한 부여
grant select, insert on my_db.emp to user_1@localhost;

 

 

with grant option

자신의 권한을 다른 user에게 부여할 수 있게 된다.

grant all privileges on my_db.* to user_2@localhost with grant option;

user_2로 로그인하여 다른 유저에거 자신의 권한을 grant 할 수  있다.

 

부여된 권한을 확인하려면

flush privileges; //변경된 내용을 메모리에 반영(권한 적용)
show grant for user_1@localhost;

 

 

권한 회수 => revoke

revoke delete on my_db.emp from user_2@localhost;

 

사용자 삭제

drop user user_2@localhost;

 

 

사용자 관리 - role

ex) 영업업무를 하는 user1, user2, user3이 있고 필요한 권한은 select, update일 경우

create role sales_role; //역할 생성
grant select, update on my_db.emp to sales_role; //역할에 권한 부여

grant sales_role to user1@localhost;
grant sales_role to user2@localhost;
grant sales_role to user3@localhost;

user1,2,3에 각각 역할을 준다.

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

파이썬 연동 예제  (0) 2021.06.02
index  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
저장 함수 예제  (0) 2021.05.15
저장 프로시저 예제  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

mysql연동위해 pymysql 설치

 

conda install pymysql

 

 

#mysql - python connection test

import pymysql #mysql과 연동하기 위해

#필요한 기본 DB 정보
host = "localhost"
user = "root"
pw = "XXXX"
db = "my_db"

#DB에 접속
conn = pymysql.connect(host= host, user = user, password = pw, db = db)

#사용할 sql문
sql = "SELECT * FROM emp LIMIT 10"

# sql문 실행/데이터 받기
curs = conn.cursor() #sql 실행시 결과를 담고 있는 버퍼를 정렬
curs.execute(sql)	#앞의 sql문 실행

data = curs.fetchall() #sql실행결과 모두 가져오기, fetchall 모든 행 가져옴, fetchone은 하나의 행만 가져옴
type(data)				#data 자료구조
data					#data 내용출력
data[0]					#첫번째 행
str(data[0][0])			#첫번째 행의 첫번째 컬럼

#db 접속 종료
curs.close()
conn.close()

sql = "SELECT * FROM emp LIMIT 10"

curs = conn.cursor()
curs.execute(sql)

row = curs.fetchone()
while(row):
	print(row)
    row = curs.fetchone()
    
# cursor는 한행씩 내려간다

 

 

GUI DB 프로그램

import sys
import pymysql
from PyQt5.QtWidgets import *

def connectDB():
    #필요한 db 정보
    host = "localhost"
    user = "root"
    pw = "Changmin97"
    db = "my_db"
    
    #db 접속
    conn = pymysql.connect(host=host, user =user, password =pw, db =db)
    return(conn)  #connection  리턴

def disconnectDB(conn):
    conn.close()
    
    

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    
    # UI 디자인 함수
    def initUI(self):
        #QLable 문자열 출력
        label1 = QLabel('ID')
        label2 = QLabel('ename')
        label3 = QLabel('job')
        label4 = QLabel('department')
    
    
        #self => 외부에서 접근 가능
        #text박스 생성 = QTextEdit
        self.text_id = QTextEdit()
        self.text_id.setFixedWidth(200)
        self.text_id.setFixedHeight(30)
    
    
        #버튼 생성, 버튼 클릭시 btn_1_clicked 실행
        btn_1 = QPushButton('Query')
        btn_1.clicked.connect(self.btn_1_clicked)
    
        #text박스 생성 = QTextEdit
        self.text_ename = QTextEdit()
        self.text_ename.setFixedWidth(200)
        self.text_ename.setFixedHeight(30)
    
        #text박스 생성 = QTextEdit
        self.text_job = QTextEdit()
        self.text_job.setFixedWidth(200)
        self.text_job.setFixedHeight(30)
    
        #text박스 생성 = QTextEdit
        self.text_dept = QTextEdit()
        self.text_dept.setFixedWidth(200)
        self.text_dept.setFixedHeight(30)
    
        #화면 배치, grid를 만들어 배치
        gbox = QGridLayout()
    
        gbox.addWidget(label1,0,0)
        gbox.addWidget(self.text_id, 0, 1)
            
        gbox.addWidget(btn_1, 0, 2)
            
        gbox.addWidget(label2,1,0)
        gbox.addWidget(self.text_ename, 1, 1)
            
        gbox.addWidget(label3,2,0)
        gbox.addWidget(self.text_job, 2, 1)
        
        gbox.addWidget(label4,3,0)
        gbox.addWidget(self.text_dept, 3, 1)
    

        self.setLayout(gbox)
        self.setWindowTitle('My Program')
        self.setGeometry(300, 300, 480,250) #창뜨는 위치, 크기
        self.show()
        
        
    #버튼 클릭 처리
    def btn_1_clicked(self):
    
        #사용자가 입력한 값 받아서 empno 저장
        empno = self.text_id.toPlainText()
            
        sql = "SELECT ename, job, danme \
                From emp e, dept d\
                where e.deptno = d.deptno\
                and empno = "+ empno
        #ex) ename '"+ename+"'" =>문자일 경우 따옴표 주의!
        conn = connectDB()
        curs = conn.cursor()
        curs.execute(sql)
            
        result = curs.fetchone() # sql 실행 결과 가져오기
            
        self.text_ename.setText(result[0])
        self.text_job.setText(result[1])
        self.text_dept.setText(restul[2])
            
        curs.close()
        disconnect(conn)
            
#END Class


#프로그램 실행, class를 생성하고 실행
if(__name__ == '__main__'):
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())            
    

 

ex 1) 

- 사원번호가 7521인 사원의 이름을 출력한다

- 이름이 SCOTT 인 사원의 부서이름을 출력한다

- 담당업무가 SALESMAN 인 모든사원의 이름을 출력한다.

- 모든 부서의 이름을 출력한다.

import pymysql #mysql과 연동하기 위해

#필요한 기본 DB 정보
host = "localhost"
user = "root"
pw = "Changmin97"
db = "my_db"

#DB에 접속
conn = pymysql.connect(host= host, user = user, password = pw, db = db)

#사용할 sql문
sql1 = "SELECT ename FROM emp WHERE empno=7521"
sql2 = "SELECT dname FROM emp, dept WHERE dept.deptno=emp.deptno and ename='scott'"
sql3 = "SELECT ename FROM emp WHERE job='salesman'"
sql4 = "SELECT dname FROM dept"

querys = [sql1, sql2, sql3, sql4]

for sql in querys:
    print(sql)
    
    # sql문 실행/데이터 받기
    curs = conn.cursor() #sql 실행시 결과를 담고 있는 버퍼를 정렬
    curs.execute(sql)	#앞의 sql문 실행 
    row = curs.fetchone() #sql실행결과 모두 가져오기, fetchall 모든 행 가져옴, fetchone은 하나의 행만 가져옴
    while(row):
        print(row)
        row	= curs.fetchone()	
        
    print("==========================================================")
    
#db 접속 종료
curs.close()
conn.close()

 

 

 

 

ex 2)

Mysql world 데이터베이스와 연동하여 다음과 같이 국가명을 입력하면 해당 국가의 정보를 출력하는 윈도우 프로그램을 작성하시오

- 매치되는 국가가 없으면 모든 항목에 공백 출력

import sys
import pymysql
from PyQt5.QtWidgets import *

def connectDB():
    #필요한 db 정보
    host = "localhost"
    user = "root"
    pw = "Changmin97"
    db = "world"
    
    #db 접속
    conn = pymysql.connect(host=host, user =user, password =pw, db =db)
    return(conn)  #connection  리턴

def disconnectDB(conn):
    conn.close()
    
    

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        
    
    # UI 디자인 함수
    def initUI(self):
        #QLable 문자열 출력
        label1 = QLabel('Country name')
        label2 = QLabel('Continent')
        label3 = QLabel('Population')
        label4 = QLabel('GNP')
        label5 = QLabel('Captial city')
        label6 = QLabel('Language')
    
    

        #text_Country_name
        self.text_Country_name = QTextEdit()
        self.text_Country_name.setFixedWidth(200)
        self.text_Country_name.setFixedHeight(30)
    
    
        #버튼 생성, 버튼 클릭시 btn_1_clicked 실행
        btn_1 = QPushButton('Query')
        btn_1.clicked.connect(self.btn_1_clicked)
    
        #text_Continent
        self.text_Continent = QTextEdit()
        self.text_Continent.setFixedWidth(200)
        self.text_Continent.setFixedHeight(30)
    
        #text_Population
        self.text_Population = QTextEdit()
        self.text_Population.setFixedWidth(200)
        self.text_Population.setFixedHeight(30)
    
        #text_GNP
        self.text_GNP = QTextEdit()
        self.text_GNP.setFixedWidth(200)
        self.text_GNP.setFixedHeight(30)
        
        #text_Captial_city
        self.text_Captial_city = QTextEdit()
        self.text_Captial_city.setFixedWidth(200)
        self.text_Captial_city.setFixedHeight(30)
        
          #text_Language
        self.text_Language = QTextEdit()
        self.text_Language.setFixedWidth(200)
        self.text_Language.setFixedHeight(30)
        
        
        
    
        #화면 배치, grid를 만들어 배치
        gbox = QGridLayout()
    
        gbox.addWidget(label1,0,0)
        gbox.addWidget(self.text_Country_name, 0, 1)
            
        gbox.addWidget(btn_1, 0, 2)
            
        gbox.addWidget(label2,1,0)
        gbox.addWidget(self.text_Continent, 1, 1)
            
        gbox.addWidget(label3,2,0)
        gbox.addWidget(self.text_Population, 2, 1)
        
        gbox.addWidget(label4,3,0)
        gbox.addWidget(self.text_GNP, 3, 1)
        
        gbox.addWidget(label5,4,0)
        gbox.addWidget(self.text_Captial_city, 4, 1)
        
        gbox.addWidget(label6,5,0)
        gbox.addWidget(self.text_Language, 5, 1)
    

        self.setLayout(gbox)
        self.setWindowTitle('Country Info')
        self.setGeometry(300, 300, 480,250) #창뜨는 위치, 크기
        self.show()
        
        
    #버튼 클릭 처리
        def btn_1_clicked(self):
    
        #사용자가 입력한 값 받아 저장
        Country_name = self.text_Country_name.toPlainText()
            
        sql = "SELECT country.name, continent, country.population, gnp, city.name, language \
                From country, city, countrylanguage\
                where country.code = city.countrycode \
                    and country.code = countrylanguage.countrycode\
                    and country.capital=city.id\
                    and IsOfficial = 'T' \
                    and country.name ="+"'"+Country_name+"'"
        #ex) ename '"+ename+"'" =>문자일 경우 따옴표 주의!
        conn = connectDB()
        curs = conn.cursor()
        curs.execute(sql)
            
        result = curs.fetchone() # sql 실행 결과 가져오기

        if result:    
            self.text_Country_name.setText(result[0])
            self.text_Continent.setText(result[1])
            self.text_Population.setText(str(result[2]))
            self.text_GNP.setText(str(result[3]))
            self.text_Captial_city.setText(result[4])
            self.text_Language.setText(result[5])
        else:
            self.text_Country_name.setText("") #매치되는 국가가 없으면 모든 항목에 공백 출력
            
            
        curs.close()
        disconnect(conn)
            
#END Class


#프로그램 실행, class를 생성하고 실행
if(__name__ == '__main__'):
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())            
    	

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

index  (0) 2021.06.02
데이터 베이스 보안  (0) 2021.06.02
저장 함수 예제  (0) 2021.05.15
저장 프로시저 예제  (0) 2021.05.15
뷰 예제  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

(1) 사원이름을 입력하면 사원의 매니저 이름을 리턴하는 함수를 작성하시오 (f_mgr)

다음과 같이 함수를 테스트한 결과를 보이시오.

select empno, ename, f_mgr(ename) as manager

from emp

CREATE FUNCTION f_mgr (e_name varchar(10))
RETURNS varchar(10)
BEGIN
    declare manager varchar(10);
    select m.ename into manager 
    from emp e, emp m
    where e.mgr=m.empno and e.ename = e_name;
RETURN manager;
END

 

 

(2) 부서번호를 입력하면 부서의 위치를 출력하는 함수를 작성하시오 (f_loc)

다음과 같이 함수를 테스트한 결과를 보이시오.

select empno, ename, job, f_loc(deptno) as loc

from emp

CREATE FUNCTION f_loc (d_no int)
RETURNS varchar(10)
BEGIN
    declare d_loc varchar(10);
    
    select loc into d_loc
    from dept
    where deptno = d_no;
    
RETURN d_loc;
END

 

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터 베이스 보안  (0) 2021.06.02
DB 파이썬 연동  (0) 2021.05.18
저장 프로시저 예제  (0) 2021.05.15
뷰 예제  (0) 2021.05.15
저장 프로시저  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

1. 사원번호를 매개변수로 입력 받아 사원번호, 이름, 담당업무, 연봉, 소속부서명을 보여주는 stored procedure 를 작성하시오 (p_emp_sel_1)

CREATE PROCEDURE p_emp_sel_1(id int)
BEGIN
	select empno, ename, job, sal, dname from emp, dept
	where emp.deptno=dept.deptno and empno = id;
END

 

2. 부서번호, 부서명, 위치를 매개변수로 입력 받아 새로운 부서 정보를 생성하는 stored procedure 를 작성하시오 (p_dept_insert_1)

CREATE  PROCEDURE p_dept_insert_1(d_num int , d_name varchar(10), d_loc varchar(10))
BEGIN
	insert into dept values(d_num, d_name, d_loc);
END

 

3. 사원번호, 사원 이름을 매개변수로 입력 받아 이름을 수정하는 stored procedure 를 작성하시오 (p_emp_update_1)

CREATE PROCEDURE p_emp_update_1 (e_num int, e_name varchar(10))
BEGIN
	update emp set ename=e_name where empno = e_num;
END

 

 

1. 사원번호를 매개변수로 입력 받아 사원의 담당업무가 ‘CLERK’ 이면 급여를 20% 올리고, 아닌 경우는 10%를 올리는 stored procedure 를 작성하시오 (p_emp_update_2)

CREATE PROCEDURE p_emp_update_2 (e_num int)
BEGIN
	declare e_job varchar(10);
    	select job into e_job
    	from emp
    	where empno=e_num;
    
    	if(e_job = 'clerk') then
			update emp 
			set sal=sal*1.2 
			where empno=e_num;
    	end if;
    
    	if(e_job != 'clerk') then
			update emp
        	set sal=sal*1.1
        	where empno=e_num;
		end if;
END

 

2. 사원번호를 매개변수로 입력 받은 후에 그 사원이 속한 부서 사람들의 연봉 합계를 구하여 출력하는 stored procedure 를 작성하시오 (p_emp_sel_2)

CREATE PROCEDURE p_emp_sel_2 (e_num int)
BEGIN
    select sum(sal) 
    from emp
    where deptno = (select deptno from emp where empno = e_num);
END

 

3. 사원번호를 매개변수로 입력 받은 후에 사원의 급여가 평균급여 이상이면 해당 사원의 근무지를 보이고, 그렇지 않으면 사원의 직무를 보이는 stored procedure 를 작성 하시오. (p_emp_sel_3)

CREATE PROCEDURE p_emp_sel_3 (e_num int)
BEGIN
	declare e_sal decimal(10,4);
    	declare avg_sal decimal(10,4);
    
    	select sal into e_sal
    	from emp
    	where empno=e_num;
    
   	 	select avg(sal) into avg_sal
    	from emp;
    
   
    	if(avg_sal <= e_sal) then
			select loc from empd where empno=e_num;
		else
			select job from emp where empno=e_num;
		end if;
END
728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

DB 파이썬 연동  (0) 2021.05.18
저장 함수 예제  (0) 2021.05.15
뷰 예제  (0) 2021.05.15
저장 프로시저  (0) 2021.05.15
  (0) 2021.05.15
블로그 이미지

아상관없어

,
반응형

1. emp dept 테이블로 부터 다음과 같은 조건을 만족하는 뷰를 생성하시오

create view empd as

select empno, ename, hiredate, sal, job, dname, loc

from emp, dept

where emp.deptno = dept.deptno;

 

2. 생성된 뷰를 이용하여 다음의 질의에 대한 sql 문을 작성하시오

모든 사원의 이름, 부서명을 보이시오

SELECT ename, dname FROM empd;

 

급여가 2500 보다 많은 사원의 사원번호, 이름, 급여, 부서위치를 보이시오

SELECT empno, ename, sal, loc FROM empd where sal >2500;

 

부서위치가 DALLAS 인 사원의 이름과 입사일자를 보이시오

SELECT ename, hiredate FROM empd where loc = 'dallas';

 

SMITH 사원의 부서위치를 보이시오

SELECT loc FROM empd where ename = 'smith';

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

저장 함수 예제  (0) 2021.05.15
저장 프로시저 예제  (0) 2021.05.15
저장 프로시저  (0) 2021.05.15
  (0) 2021.05.15
데이터베이스 예제 4  (0) 2021.04.20
블로그 이미지

아상관없어

,
반응형

저장 프로시저는 MySQL 5.0 이상 버전부터 사용가능하다.

 

여러 sql문을 하나의 sql문처럼 정리하여 call 명령으로 실행할 수 있게 만든 것.

=> 데이터베이스 내에 미리 컴파일되어 저장된 sql 코드

=> 사용자 프로그램에서 호출하거나, 다른 저장 프로시저에서 호출가능

=> 결과를 서버에 저장, 컴파일 하고 캐쉬에 저장한뒤 실행함, 

장점

=> 데이터베이스 내에서 sql 명령을 컴파일할때 캐시를 이용할 수 있어 처리가 빠름

=> 어플리케이션마다 복수의 SQL문 기술할 필요 없이 만들어진 저장 프로시저를 사용하면 다른 어플리케이션을 수정하여 컴파일 할 필요 없음.

=> 저장 프로시저는 만들어지는 순간에 구문이 검사됨, 따라서 DBA의 에러를 감소시킬 수 있음(실행전 검사)

=> SQL문을 직접 실행시킬 수 없는 사용자들도 저장 프로시저만 실행시킬 수 있는 권한을 가지게 할 수 있다.

 

단점

=> 접하기 어렵다.

=> DBMS 제품마다 문법이 다르다(비표준화)

=> 저장프로시저를 남발하는 경우 유지보수가 어렵다.

 

함수와의 차이점

저장프로시저 : 일반적으로 return 값이 없는 프로그램, CALL에 의해서 호출

함수 : return 값이 있는 프로그램, MAX(), min()과 같이 SQL문 안에서 사용

 

- 저장 프로시저 생성

CREATE PROCEDURE 저장프로시저이름()
BEGIN 
	SQL문 1;
    	SQL문 2;
END

BEGIN ~ END 사이에 원하는 SQL문들을 작성하면 된다.

 

** 구분문자 문제

위와 같이 작성시 BEGIN ~ END안에서 SQL문이 작성이 덜 되었더라도 ;를 만나게되면 CREATE PROCEDURE 을 실행하게되어 완성되지 않은 상태로 저장프로시저가 생성된다.

CREATE PROCEDURE 저장프로시저이름(인수이름 자료형)
BEGIN 
	SQL문 1;
    	SQL문 2
END

와 같이 될 경우 MySQL 콘솔창은 ;이 입력되면 ;이전단계까지의 명령문을 실행하게 되기때문이다.

 

따라서 

저장 프로시저에서 END를 입력하고난 뒤 CREATE PROCEFURE 명령이 실행되게 해야한다.

 DELIMITER를 사용하여 구분문자를 ;대신 다른 문자로 변경한다.

EX) DELIMITER // 혹은 DELIMITER =

와 같이원하는 문자를 적으면 된다.

 

DELIMITER //                  =>구분 문자를 ;에서 //로 변경
CREATE PROCEDURE pr1()
BEGIN
	SELECT * FROM tb;
    	SELECT * FROM tb1;
END
//                            =>//구분문자를 만났으므로 이전까지 입력된 명령을 수행
DELIMITER ;                   => 구분문자를 다시 ;로 변경

 

 

- 저장 프로시저 실행

CALL 저장프로시저이름;

ex) CALL pr1();를 실행하면

자동으로 SELECT * FROM tb;와 SELECT * FROM tb1;가 실행된다.

 

- 저장 프로시저 인수 사용

PROCEDURE 저장프로시저이름(인수이름 자료형);

예를 들어 sales가 200 이상인 값을 보려고 할때

select * from tb where sales>=d;와 같이 설정하면

DELIMITER //                 
CREATE PROCEDURE pr1(d INT)
BEGIN
	SELECT * FROM tb WHERE sales>=d;
END
//                            
DELIMITER ;                  

d를 인자로 받아들여 pr1(200)을 실행하면 

select * from tb where sales>=200;이 된다.

 

 

- 작성된 저장 프로시저 내용 표시

SHOW CREATE PROCEDURE 저장프로시저이름;

ex) SHOW CREATE PROCEDURE pr1;

pr1의 프로시저 내용을 볼 수 있게 된다.

 

- 저장 프로시저 삭제

DROP PROCEDURE 저장프로시저이름;

 

 

- 저장 함수

저장 프로시저와 유사하지만, 실행했을 때 값을 반환한다.

CREATE FUNCTION 저장함수이름(인수이름 자료형) RETURNS 반환값자료형
BEGIN
	SQL문 ....
    	RETURN 반환값식
END

 

* DECLARE

저장 함수에서 변수를 사용하려면 DECLARE로 정의해야한다.

DECLARE 변수이름 자료형;

예시를 보면

CRETAE FUNCTION func() RETURNS DOUBLE          => 함수의 반환형은 double
BEGIN
	DECLARE r DOUBLE;                      => 변수 r 선언
    	SELECT AVG(sales) INTO r FROM tb;      => AVG(sales)값을 r에 저장
       	RETURN 	r;                             => r을 반환
END

 

- 저장함수 삭제

DROP FUNCTION 저장함수이름;

 

- 저장함수 내용 표시

SHOW CREATE FUNCTION 저장함수이름;

저장 함수의 내용을 볼 수 있게된다.

 

 

- 트리거

테이블에 대해 어떤 처리를 실행하면 이에 반응하여 설정한 명령이 자동으로 실행되는 구조

INSERT, UPDATE, DELETE 등 명령이 실행될 때, 트리거로 설정한 명령이 자동으로 실행되게 할 수 있다.

EX) 테이블의 레코드 변경시, 변경한 내용을 다른 테이블에 기록하도록 트리거를 만들 수 있음

따라서 트리거는 처리를 기록하거나, 처리가 실패할 경우를 대비하여 만들어 놓으면 좋다.

 

트리거는 INSERT, UPDATE, DELETE 등 명령이 실행되기 직전(BEFORE) 또는 직후(AFTER)에 호출되어 실행된다.

 

즉, 어떤 데이터를 처리하기 전에 호출되거나 어떤 데이터를 처리한 후에 호출된다.

 

또한 테이블에서 어떤 데이터를 처리하기 전의 값은 OLD.칼럼이름.

처리한 후의 값은 NEW.칼럼이름으로 얻을 수 있다.(추출할 수 있다.)

 

명령에 따라서 칼럼 값을 추출할 수도 있고 없을 수도 있다.

명령 실행전(old.칼럼이름) 실행후(new.칼럼이름)
insert old.칼럼이름 추출 불가 가능
delete 가능 new.칼럼이름 추출불가
update 가능 가능

 

 

- 트리거 생성

CREATE TRIGGER 트리거이름 BEFORE(또는 AFTER) DELETE(UPDATE,INSERT 등과 같은 명령)
ON 테이블 이름 FOR EACH ROW
BEGIN
	변경전(OLD.칼럼이름)을 이용한 처리                      ====> 또는 변경후(NEW.칼럼이름)
END

 

 

EX) tb1에서 삭제한 레코드를 tb1m에 삽입하는 트리거 작성

DELIMITER //
CREATE TRIGGER tr1 BEFORE DELETE ON tb1 FOR EACH ROW                  
===> delete에 반응, 삭제하기 직전의 값을 넣으므로 before, for each row 각 행에 대해 수행
BEGIN
	INSERT INTO tb1m VALUES(OLD.number, OLD.name, OLD.age);
END
//
DELIMIER ;

tb1에서 레코드가 삭제될때, tb1m에 삭제된 레코드가 입력되게 된다.

DELETE FROM tb1;을 하여 모든 레코드를 삭제하더라도 tb1m에 삭제된 레코드들이 저장되게 된다.

따라서  INSERT INTO tb1 SELECT * FROM tb1m;과 같이 다시 복원을 할 수도 있다.

 

 

- 트리거 확인

SHOW TRIGGERS;

 

- 트리거 삭제

DROP TRIGGER 트리거이름;

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

저장 프로시저 예제  (0) 2021.05.15
뷰 예제  (0) 2021.05.15
  (0) 2021.05.15
데이터베이스 예제 4  (0) 2021.04.20
데이터베이스 예제 3  (0) 2021.04.20
블로그 이미지

아상관없어

,

공부/데이터베이스 2021. 5. 15. 02:00
반응형

select를 한 결과를 가상 테이블에 저장한 것

가상 테이블이 뷰임

=> 하나의 테이블에 대하여 서로 다른 관점으로 보기 원할때,

=> 일반 사용자에게는 감추어야할 컬럼이 있을때 그것을 제외하고 뷰를 만들어 제공하여 보안 유지

=> 자주 사용하는 복잡한 질의문을 미리 뷰로 정의하여 두고 간편하게 사용할 때

=> 물리적인 데이터를 갖지 않음

=> 뷰 갱신연산은 경우에따라 실행(view에 정의된 것)될 수 도 안될(뷰에 정의되지 않은 값 ex) not null인데 null입력) 수도 있음

 

- 뷰 생성

CREATE VIEW 뷰이름 AS SELECT 칼럼이름 FROM 테이블이름 WHERE 조건;

EX) CREATE VIEW v1 AS SELECT name, age FROM tb1;

SELECT * FROM v1;

 

- 뷰에서 칼럼 값 변경

뷰는 참조 테이블의 일부분을 표시함

따라서 참조 테이블의 값이 변경되면 뷰의 값도 변경

뷰는 참조 테이블의 일부분을 표시하면서 참조테이블의 데이터 창구이기도 함

따라서 뷰의 값이 변경되면 참조 테이블의 값도 변경

ex) UPDATE v1 SET name='주임 강신우' WHERE name='강신우';

 

- 뷰에서 INSERT ??

뷰는 가상테이블이므로, 뷰에 INSERT하는 것은 테이블의 일부에만 데이터를 추가하게 되는 것임

값을 추가하지 않은 칼럼은 default 값이 입력된다.

UNION이나 JOIN, 하위질의를 사용하는 뷰에선 INSERT나 UPDATE를 사용할 수 없다.

 

- 뷰의 조건에 맞지 않는 값 뷰에 추가

ex) create view v3 as select number, sales from tb where sales>=100;

sales가 100이상인 조건의 뷰 v3를 만들고 v3에 sales가 100보다 작은 값을 넣으면 어떻게 될까?

INSERT INTO v3 VALEUS('test', 90);

 

SELECT * FROM v3;   ==> 기존과 동일하게 보인다. 

SELECT number, sales FROM tb1;  ==> test, 90이라는 값이 추가된 것을 알 수 있다.

 

 

- 뷰의 조건에 맞지 않는 값 뷰에 추가시 제한걸기

create view v4 as create number, sales from tb where sales>100 with check option;

뷰 생성시 with check option을 추가하면 조건에 맞지 않는 데이터를 추가하지 못하게 한다.

위 예에선 sales가 100이하인 값을 추가하지 못하게 된다.

 

- 뷰 덮어쓰기

이미 같은 이름의 뷰가 존재할때 덮어쓰기하여 뷰를 생성

 

CREATE OR REPLACE VIEW v1 AS  select now();

와 같이 CREATE OR REPLACE VIEW라고 해주면 된다.

 

그러면 기존 뷰 v1은 삭제되고 now를 표시하는 새로운 뷰 v1이 생성된다.

뷰의 존재 여부에 상관없이 뷰를 생성할 수 있게 해주는 방법이다.

 

- 뷰 칼럼 구조 변경

ALTER VIEW 뷰이름 AS SELECT 칼럼이름 FROM 테이블이름;

EX) ALTER VIEW v1 AS SELECT name, age FROM tb1;

 

- 뷰 삭제

DROP VIEW 뷰이름;

*삭제할 뷰가 없는 경우 오류가 발생하므로 IF EXISTS 사용

ex) DROP VIEW IF EXISTS v1;

 

 

 

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

뷰 예제  (0) 2021.05.15
저장 프로시저  (0) 2021.05.15
데이터베이스 예제 4  (0) 2021.04.20
데이터베이스 예제 3  (0) 2021.04.20
데이터베이스 예제 2  (0) 2021.04.20
블로그 이미지

아상관없어

,
반응형

1. 다음과 같은 컬럼을 갖는 테이블 student 를 생성하시오. 자료형은 각자 알아서 한다)

CREATE TABLE student (

sid INT NOT NULL PRIMARY KEY,

sname VARCHAR(10),

major VARCHAR(10),

gender CHAR(1) DEFAULT 'M',

reg_order INT,

lastchg DATETIME );

 

2. 4명의 학생 정보를 입력하시오 (남학생 2명, 여학생 2명)

INSERT INTO student (sid, sname, major, gender, reg_order)

VALUES(32210001, 'student1', 'software', 'M', 1),

(32210002, 'student2', 'software', 'F', 2),

(32210003, 'student3', 'software', 'M', 3),

(32210004, 'student4', 'software', 'F', 4);

 

3. student 테이블에 score (학점) 컬럼을 추가하시오

ALTER TABLE student ADD score INT;

 

4. student 테이블에서 reg_order 를 admit_order 로 변경하시오 => 다시

ALTER TABLE student CHANGE COLUMN reg_order admit_order INT;

ALTER TABLE studnet CHAGE reg_order admit_order INT;

 

 

5. 남학생들의 학점은 2.5 로 여학생들의 학점은 3.0 으로 입력하시오 (두개의 SQL문 필요)

UPDATE student SET socre=2.5 WHERE gender='M';

UPDATE studnet SET score=3.0 WHERE gender='F';

 

7. 근무지가 ‘BOSTON’ 인 사원에게 보너스(comm)를 급여의 50% 수준으로 지급 하도록 입력하시오

UPDATE emp SET comm = sal/2 WHERE deptno=(SELECT deptno FROM dept WHER loc='BOSTON');

 

8. 입사년도가 1980 년도인 사원들의 급여를 5000 씩 올리시오

UPDATE emp SET sal = sal+5000

WHERE YEAR(hirdate) = 1980;

 

4. emp 테이블에서 연봉이 4000 이상인 사람의 사원번호, 이름, 매니저이름, 연봉 데이터를 top_sal.csv 파일에 저장하시오

SELECT e.empno, e.ename, m.ename, e.sal INTO OUTFILE 'C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Uploads\\top_sal.csv'

FIELDS TERMINATED BY ','

LINES TERMINATED BY '\n'

FROM emp e, emp m

WHERE e.sal >= 4000 AND e.mgr=m.empno;

 

5. dept 테이블의 데이터를 dept.csv 파일에 저장하시오

SELECT * INTO OUTFILE 'C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Uploads\\dept.csv'

FIELDS TERMINATED BY ','

LINES TERMINATED BY '\n'

FROM dept;

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

저장 프로시저  (0) 2021.05.15
  (0) 2021.05.15
데이터베이스 예제 3  (0) 2021.04.20
데이터베이스 예제 2  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
블로그 이미지

아상관없어

,
반응형

1. DALLAS 에서 근무하는 사원의 이름, 부서명, 담당업무를 보이시오

SELECT ename, dname, job

FROM emp, deptno

WHERE emp.deptno=deptno.deptno AND loc='DALLAS';

 

2. DALLAS 에서 근무하는 사원중 연봉이 4000 이하인 사람은 몇 명인가

SELECT COUNT(*) FROM emp, dept

WHERE emp.deptno=dept.deptno AND loc='DALLAS' AND sal<=4000;

 

3. PRESIDENT (사장)이 근무하는 지역은 어디인가

SELECT loc FROM emp, dept WHERE emp.deptno=dept.deptno AND job='PRESIDENT';

 

4. 모든 매니저의 이름과 부하직원의 이름을 보이시오 (매니저이름으로 정렬하여 보 이시오)

SELECT m.ename, e.ename FROM emp e, emp m

WHERE e.mgr=m.empno 

ORDER BY m.ename;

 

5. 모든 매니저의 이름과 부하직원의 숫자를 보이시오 => 다시

SELECT m.ename, COUNT(*) FROM emp e, emp m

WHERE e.mgr=m.empno

GROUP BY m.ename;

 

 

6. 각 지역별로 근무하는 사원들의 연봉 합계를 보이시오 (지역명, 연봉합계)

SELECT loc, SUM(sal) FROM emp, dept 

WHERE emp.deptno=dept.deptno GROUP BY loc;

 

7. 매니저가 아닌 (부하직원이 없는) 사원들은 몇 명인가? -중첩사용과 미사용 둘다 =>다시 

SELECT COUNT(*) FROM emp e

WHERE e.empno NOT IN (SELECT mgr  FROM emp WHERE mgr IS NOT NULL);

 

SELECT COUNT(empno) - COUNT(distinct mgr) from emp;

(전체 직원수에서 매니저 수를 빼면 매니저가 아닌 직원 수만 남음)

 

8. 매니저가 아닌 (부하직원이 없는) 사원들의 연봉합계는 얼마인가 => 다시

SELECT SUM(sal) FROM emp

WHERE empno NOT IN (SELECT mgr FROM emp WHERE mgr IS NOT NULL);

 

 

9. 매니저이름, 부하직원이름, 부서명 을 보이시오 (매니저이름으로 정렬)

SELECT m.ename, e.ename, dept.dname FROM emp e, emp m, dept

WHERE e.mgr=m.empno AND dept.deptno=m.deptno ORDER BY m.ename;

 

 

10. SCOTT 의 매니저는 연봉이 얼마인가

SELECT m.sal FROM emp e, emp m

 WHERE e.mgr=m.empno AND e.ename='SCOTT';

 

11. Asia 지역에 있는 국가의 국가명, 도시명을 보이시오

SELECT country.name, city.name FROM country, city WHERE country.continent='Asia' AND country.code=city.counrtycode;

 

12. South Korea 에 있는 도시명, 도시 인구수(population)를 보이시오

SELECT city.name, city.population FROM country, ciry WHERE country.code=city.countrycode AND country.name = 'SOUNT KOREA';

 

13. South Korea 에 있는 도시중 인구수가 100만 이상인 도시의 도시명, 도시 인구 수(population)를 보이시오

SELECT city.name, city.population FROM city, counrty WHERE

city.popluation>=1000000 AND city.counrtycode=country.code AND country.name='south korea';

 

14. GNP 가200 미만인 국가의 국가명, 도시명, 도시 인구수를 보이시오

SELECT country.name, city.name, city.popluation FROM country, city 

WHERE country.code=city.countrycode AND country.gnp < 200;

 

15. Laos 에 있는 도시수를 보이시오

SELECT COUNT(city.name) FROM country, city WHERE country.code=city.countrycode AND country.name='laos';

 

16. 국가명, 그 국가의 도시의 수를 보이시오 => 다시

SELECT country.name, COUNT(*) FROM country, city

WHERE country.code=city.countrycode

GROUP BY country.name;

 

 

17. 국가명, 그 국가 도시의 평균 인구수를 보이시오

SELECT country.name, AVG(city.popluation) FROM country, city WHERE

country.code=city.countrycode GROUP BY country.name;

 

18. 국가 인구수가 1000만명이 안되는 국가의 국가명, 도시명을 보이시오 => 다시

SELECT country.name, city.name FROM country, city

WHERE country.code=city.countrycode AND country.popluation < 10000000;

 

19. EUROPE 에 있는 국가중 국가 인구수가 1000만명이 안되는 국가의 국가명, 도시 명을 보이시오

SELECT country.name, city.name FROM country, city WHERE

country.code=city.countrycode  AND country.continent='EUROPE' AND country.population<10000000;

 

20. Asia 지역에 있는 국가중 GNP가 20000 이상이고 인구수가 3000만이상인 국가 의 국가명, GNP, 도시명, 도시인구수를 보이시오

SELECT country.name, city.name, city.population FROM country, city

WHERE country.code=city.countrycode AND country.continent ='Asia' AND gnpe >=20000 AND couintry.population>=30000000;

 

1. 연봉을 가장 적게 받는 사원의 이름, 연봉, 부서명을 보이시오

SELECT ename, sal, dname FROM emp, dept 

WHERE emp.deptno=dept.deptno AND sal = (SELECT MIN(sal) FROM emp);

 

2. 연봉을 평균 이상 받는 사원들의 이름, 연봉, 근무지를 보이시오

SELECT ename, sal, loc FROM emp, dept

WHERE emp.deptno=dept.dpetno AND sal >= (SELECT AVG(sal) FROM emp);

 

3. 연봉을 가장 적게 받는 사원의 매니저는 누구인가?

SELECT e.mgr FROM emp e, emp m 

WHERE e.mgr=m.empno AND e.sal = (SELECT MIN(sal) FROM emp);

 

4. 연봉을 가장 많이 받는 사원과 적게 받는 사원의 이름, 연봉을 보이시오 => 다시

SELECT ename, sal FROM emp

WHERE sal = (SELECT MIN(sal) FROM emp) OR sal=(SELECT MAX(sal) FROM emp);

 

5. 연봉을 가장 많이 받는 사원과 적게 받는 사원을 제외한 나머지 사원들의 총 연봉 합계를 보이시오 => 다시

SELECT SUM(sal) FROM emp

WHERE sal != (select max(sal) from emp) and sal != (select min(sal) from emp)

 

6. SALES 부서에 속한 사원들과 동일한 담당업무를 갖는 사원들의 이름, 담당업무를 보이시오 (단 SALES 부서에 속한 사원은 제외) => 다시

SELECT ename, job FROM emp, dept

WHERE dname <> 'SALES' (SALES에 속한 사람은 제외)

AND emp.deptno=dept.deptno

AND job IN(SELECT job FROM emp, dept WHERE emp.deptno=dept.deptno AND dname = 'SALES')

(SALES 부서에 속한 사원들이 가지는 업무 )

 

 

 

7. 연봉을 평균보다 500 이상 적게 받는 사원들의 이름, 부서명, 연봉을 보이시오

SELECT ename, dname, sal FROM emp, dept

WHERE emp.deptno=dept.deptno 

AND sal + 500 < (SELECT AVG(sal) FROM emp);

 

8. JAMES 보다 입사일이 빠른 사원들의 이름, 담당업무, 입사일을 보이시오

SELECT ename, job, hiredate FROM emp

WHERE hiredate < (SELECT hiredate FROM emp WHERE ename='JAMES');

 

9. ADAMS 보다 연봉을 많이 받는 사람은 모두 몇 명인가

SELECT COUNT(*) FROM emp

WHERE sal > (SELECT sal FROM emp WHERE ename='ADAMS');

10. GNP가 가장 높은 국가의 국가명, GNP 를 보이시오

SELECT name, gnp FROM country

WHERE gnp = (SELECT MAX(gnp) FROM country);

 

11. 인구수가 가장 적은 국가의 국가명, GNP 를 보이시오

SELECT name, gnp FROM country

WHERE popluation=(SELECT MIN(popluation) FROM country);

 

12. 인구수가 평균 이상인 국가중 GNP가 50000 이상인 국가의 이름과 GNP 를 보이 시오

SELECT name, gnp FROM country 

WHERE popluation >= (SELECT AVG(popluation) FROM country) AND gnp >= 50000

 

13. 한국(South Korea)보다 GNP 가 높은 ASIA 국가들의 이름과 GNP를 보이시오

SELECT name, gnp FROM country

WHERE gnp > (SELECT gnp FROM country WHERE name='South Korea') AND continent = 'ASIA';

 

14. 일본(Japan)보다 인구수가 많은 ASIA 국가들의 이름, 인구수를 보이시오

SELECT name, population FROM country 

WHERE population > (SELECT population FROM country WHERE name='Japan');

 

 

15. 영토면적(SurfaceArea)이 가장 작은 국가의 이름, 영토면적을 보이시오

SELECT name, surfacearea FROM country

WHERE surfacearea = (SELECT MIN(surfacearea) FROM counrty);

 

16. Canada 보다 영토 면적이 넓은 국가는 모두 몇나라인지 보이시오

SELECT COUNT(*) FROM country WHERE 

surfaceaera > (select surfaceaera from country where name='Canada');

 

1. 연봉을 적게 받는 하위 5 명의 이름, 부서명, 연봉을 보이시오

SELECT ename, dname, sal FROM emp, dept

WHERE emp.deptno=dept.deptno 

ORDER BY sal LIMIT 5;

 

2. 연봉을 평균 보다 적게 받는 사람들 중에서 연봉이 많은 순서대로 3명을 보이시오 (사원번호, 이름, 연봉)

SELECT empno, ename, sal FROM emp

WHERE sal < (SELECT AVG(sal) FROM emp) 

ORDER BY sal DESC 

LIMIT 3;

 

3. SCOTT 보다 연봉을 많이 받는 사람들 중에서 SCOTT 와 연봉이 비슷한 사람 3 명의 이름, 부서명, 연봉을 보이시오

SELECT ename, dname, sal FROM emp, dept

WHERE emp.deptno=dept.deptno AND sal>(SELECT sal FROM emp WHERE ename='SCOTT')

ORDER BY sal

LIMIT 3;

 

4. BLAKE 보다 입사일이 늦은 사람들 중에서 상위 2명을 제외하고 3명의 이름, 부서 명, 입사일자를 보이시오 (입사일자가 빠른순으로)

SELECT ename, dname, hiredate FROM emp, dept

WHERE emp.deptno=dept.deptno AND hiredate >(SELECT hiredate FROM emp WHERE ename='BLAKE')

ORDER BY hiredate

LIMIT 2, 3;

 

5. 연봉금액이 SMITH 와 FORD 사이인 사원의 이름, 연봉을 보이시오. (단 SMITH 와 FORD 는 누가 더연봉을 많이 받는지 알 수 없다) => 다시

SELECT ename, sal FROM emp

WHERE sal BETWEEN (SELECT MIN(sal) FROM emp WHERE ename='SMITH' OR ename='FORD') 

AND (SELECT MAX(sal) FROM emp WHERE ename='SMITH' OR ename='FORD') ;

 

SMITH와 FORD를 포함하지 않으려면  AND ename NOT IN('SMITH', 'FORD')

 

 

6. 소속된 사원의 연봉 총액이 많은 상위 2개의 부서의 이름과, 연봉 총액을 보이시 오

SELECT dname, SUM(sal) WHERE emp, dept

WHERE emp.deptno=dept.deptno 

GROUP BY dname

ORDER BY SUM(sal) DESC

LIMIT 2;

 

 

1. SALES 부서에 근무하는 사원들의 연봉을 월급으로 환산하여 보이되 소수점 이하 는 버리고 보이시오 (사원이름, 월급)

SELECT FLOOR(sal/12);

 

2. 사원의 이름과 사원의 근무지를 하나의 문자열로 만들어 보이시오

SELECT CONTACT(ename, loc) FROM emp, dept

WHERE emp.deptno=detp.deptno;

 

3. 담당업무가 CLERK 인 사원의 이름과 사원의 매니저 이름을 보이되 매니저 이름 은 앞 세글자만 보이시오 => 다시

SELECT e.ename, LEFT(m.ename, 3) FROM emp e, emp m 

WHERE e.job='CLERK' AND e.mgr= m.empno;

 

4. 연봉 3000 이상인 사원의 이름, 담당업무를 보이되 담당업무가 MANAGER 인 경 우는 업무명을 BOSS 로 바꾸어 보이시오 => 다시

SELECT ename, REPLACE(job, 'MANAGER', 'BOSS') FROM emp 

WHERE sal >= 3000;

 

5. 현재 날짜와 시간을 출력 하시오

SELECT NOW();

 

6. 1981년과 1982년에 입사한 사원의 이름, 입사일자를 보이시오 (YEAR 함수 이용 할 것) => 다시

SELECT ename, hiredate FROM emp

WEHRE YEAR(hiredate) IN (1981, 1982);

 

 

7. SCOTT 사원의 입사일부터 오늘까지 근무한 날수를 보이시오 => 다시

TO_DAYS =>  00년 00월 00일 부터 날짜까지의 일자수

SELECT TO_DATYS(CURDATE()) - TO_DAYS(hiredate) + 1 (입사날도 근무일이다)

FROM emp WHERE ename = 'SCOTT'; 

 

8. 2019년 7월 12일은 2019년 1월 1일을 기준으로 몇번 째 날인가 => 다시

SELECT DAYOFYEAR('2019-07-12');

 

 

9. 입사한 날의 요일이 월요일~수요일인 사원의 이름, 급여를 보이시오 => 다시

SELECT ename, sal FROM emp

WHERE WEEKDAY(hiredate) IN (0, 1, 2);

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

  (0) 2021.05.15
데이터베이스 예제 4  (0) 2021.04.20
데이터베이스 예제 2  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
정리  (0) 2021.04.19
블로그 이미지

아상관없어

,
반응형

1. 모든 사원들의 이름을 알파벳 역순으로 보이시오 => 다시

SELECT ename FROM emp ORDER BY ename DESC;

 

2. 모든 담당업무명을 알파멧순으로 보이시오 => 다시

SELECT DISTINCT job FROM emp ORDER BY job;

 

3. 모든 사원의 이름과 업무 , 급여를 급여순으로 보이시오

SELECT ename, job, sal FROM emp ORDERY BY sal;

 

4. 모든 사원의 이름과 부서번호를 입사일자순으로 보이시오

SELECT ename, deptno FROM emp ORDER BY hiredate;

 

5. 모든 사원의 사원번호, 이름, 급여를 부서번호순으로 보이시오

SELECT empno, ename, sal FROM emp ORDER BY deptno;

 

6. 담당업무별 평균연봉을 보이시오

SELECT AVG(sal) FROM emp GROUP BY job;

 

7. 부서별 평균 연봉을 보이되 많은연봉 우선으로 보이시오 => 다시

SELECT deptno, SUM(sal) FROM emp GROUP BY deptno ORDER BY SUM(sal) DESC;

 

8. 각 부서별 최고 연봉을 보이시오

SELECT deptno, MAX(sal) FROM emp GROUP BY deptno;

 

9. 모든 사원의 정보담당업무에 대해 오름차순으로, 그리고 같은 업무내에서는 연봉내림차순으로 정렬하여보이시오 => 다시

SELECT * FROM emp ORDERY BY job, sal DESC;

 

10. 각 매니저별 담당사원의 인원수, 평균 연봉을 보이시오 => 다시

SELECT mgr, COUNT(*), AVG(sal) FROM emp WHERE mgr IS NOT NULL GROUP BY mgr;

 

 

11. 각 담당 업무별로 최고 연봉과 최저 연봉을 보이시오

SELECT job, MAX(sal), MIN(sal) FROM emp GROUP BY job;

 

12. 담당업무별 인원수, 평균 연봉을 보이되 업무별 인원수가 3 명 이상인 경우에 대 해서만 보이시오

=>다시

SELECT job, COUNT(*), AVG(sal) FROM emp GROUP BY job HAVING COUNT(*) >= 3;

 

13. 각 부서별 부서번호, 사원 수, 연봉합계를 보이시오

SELECT deptno, COUNT(*), SUM(sal) FROM emp GROUP BY deptno;

 

14. 각 부서별 부서번호, 사원 수, 연봉합계를 보이되 사원 수가 3 명 이상인 부서의 정보만 보이시오.

SELECT deptno, COUNT(*), SUM(sal) FROM emp GROUP BY deptno HANVING COUNT(*) >= 3;

 

15. 부서번호 , 부서별 사원 수, 연봉 합계를 보이되 급여합계가 4000~5000 사이인 경우만 보이시오 . 단, 입사일자가 1981-01-01 이전 사원은 제외하고, 연봉합계가 많 은 순으로 출력하시오 

 

SELECT deptno, COUNT(*), SUM(sal)

FROM emp

WHERE hiredate >= '1981-01-01'

GROUP BY deptno HAVING SUM(sal) BETWEEN 4000 AND 5000;

ORDER BY SUM(sal) DESC;

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터베이스 예제 4  (0) 2021.04.20
데이터베이스 예제 3  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
정리  (0) 2021.04.19
파일 사용  (0) 2021.04.14
블로그 이미지

아상관없어

,
반응형

1. BOSTON 에 있는 부서의 이름은 무엇인가

SELECT dname

FROM dept

WHERE dname='BOSTON';

 

2. 담당업무가 ANALYST 인 사원의 이름, 입사일자를 보이시오

SELECT ename, hiredate

FROM emp

WHERE job = 'ANALYST';

 

3. 입사일자가 1981년 9월 1일 이후인 사원의 이름과 입사일자를 보이시오

SELECT ename, hiredate

FROM emp

WHERE hiredate >= '1981-09-01';

 

4. 연봉이 3000에서 4000 사이인 사원의 이름, 연봉을 보이시오

SELECT ename, sal

FROM emp

WHERE sal BETWEEN 3000 AND 4000;

 

5. 사장의 이름을 보이시오 (힌트: 사장은 매니저가 없다)

SELECT ename 

FROM emp 

WHERE mgr IS NULL;

SELECT ename FROM emp WHERE job = 'president';

 

6. 담당업무가 MANAGER 가 아닌 사원들의 이름, 담당업무를 보이시오

SELECT ename, job FROM emp WHERE job <> 'MANAGER';

 

7. 담당업무가 CLERK, ANALYST, SALESMAN 인 사원들의 이름, 담당업무, 급여를 보이시오

SELECT ename, job, sal FROM emp WHERE job IN ('CLERK', 'ANALYST', 'SALESMAN');

 

8. 연봉이 3000 에서 4000 사이 이거나 담당업무가 MANAGER 인 사원의 이름, 연 봉을 보이시오

SELECT ename, sal FROM emp WHERE (sal BETWEEN 3000 AND 4000) OR (job='MANAGER'); 

 

9. 보너스를 받는 사원들의 이름과 보너스 금액을 보이시오. (보너스가 0인 경우도 받 는 것으로 간주)

SELECT ename, comm FROM emp WHERE com IS NOT NULL;

 

10. 부서번호가 20 인 사원 중에서 담당업무가 CLERK 이고 매니저의 사원번호가 7902 인 사람의 이름을 보이시오

SELECT ename FROM emp WHERE deptno=20 AND job='CLERK' and mgr=7902; 

 

1. 담당 업무가 CLERK 인 사원은 모두 몇 명인가

SELECT COUNT(*) FROM emp WHERE job='CLERK';

 

2. 담당 업무가 CLERK 인 사원의 최고연봉 금액과 최저 연봉금액, 그리고 두 금액 의 차이 금액을 보이시오

SELECT MAX(sal), MIN(sal), MAX(sal) - MIN(sal) FROM emp FROM emp WHERE job='CLERK';

 

3. 입사일이 1981년 9월 1일 이후인 사원의 평균 연봉을 보이시오

SELECT AVG(sal) FROM emp WHERE hiredate > '1981-09-01';

 

4. 매니저의 사원번호가 7698, 7639, 7782 이 아닌 사원의 이름, 담당업무를 보이시오

SELECT ename, job FROM emp WHERE mgr IN (7698, 7639, 7782);

 

5. 1982 년도 와 1983 년도에 입사한 사원의 이름, 입사일자를 보이시오

SELECT ename, hiredate FROM emp WHERE hiredate >= '82/01/01' and hiredate <= '83/12/31' ; 

 

6. 담당업무 이름에 NA 를 포함하고 있는 사원의 이름, 담당업무를 보이시오

SELECT ename, job FROM emp WHERE job LIKE '%NA%';

 

7. 보너스를 받는 사원의 이름과 보너스와 연봉을 합한 금액을 보이시오

SELECT ename, sal+comm FROM emp WHERE comm IS NOT NULL;

 

8. 모든 사원의 연봉을 10% 올려주려면 현재보다 돈이 얼마나 더 있어야 하는지 보 이시오

SELECT SUM(sal*1.1) - SUM(sal) FROM emp;

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터베이스 예제 3  (0) 2021.04.20
데이터베이스 예제 2  (0) 2021.04.20
정리  (0) 2021.04.19
파일 사용  (0) 2021.04.14
트랜젝션  (0) 2021.04.14
블로그 이미지

아상관없어

,

정리

공부/데이터베이스 2021. 4. 19. 22:55
반응형

-테이블 생성

CREATE TABLE 테이블 이름 {

칼럼이름1 자료형,

칼럼이름2 자료형,

.....

};

 

 

-데이터 추가

INSERT INTO 테이블이름 VALUES(데이터1, 데이터2....)

INSERT INTO 테이블이름 (칼럼이름1, 칼럼이름2.....) VALUES(데이터1, 데이터2....);

 

 

-다른 테이블의 레코드 복사

INSERT INTO 테이블이름 SELECT * FROM 복사할테이블이름;

 

-테이블의 칼럼 구조만 복사

CREATE TABLE 새테이블이름 LIKE 복사할테이블이름;

 

-특정 칼럼 선택 후 복사

INSERT INTO tb1 (name) (SELECT number FROM tb1)

 

-레코드수 제한 표시 LIMIT

SELECT 칼럼이름 FROM 테이블이름 LIMIT 표시할 레코드수;

SELECT * FROM tb LIMIT 3;

 

SELECT * FROM tb LIMIT 3 OFFSET 3

4번째 레코드부터 표시

 

 

 

 

-not equal <>

 

-LIKE

'%A%' => %는 임의의 문자열

'__A%' => -는 문자하나를 뜻함

 

-IS NULL

SELECT * FROM tb1 WHERE age IS NULL;

 

-중복 데이터 제거 DISTINCT

SELECT DISTINCT number FROM tb;

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터베이스 예제 2  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
파일 사용  (0) 2021.04.14
트랜젝션  (0) 2021.04.14
SQL JOIN  (0) 2021.03.30
블로그 이미지

아상관없어

,
반응형

* CVS

반점을 구분한 값이라는 뜻

파일의 내용은 데이터가 , 으로 구분된 형식의 문자만으로 이루어져있다.

EX) 

1, A, 55

2, B, 26

3, C, 79

와 같이 데이터는 반점으로 구분되고 한행이 끝날때마다 줄바꿈을 한다.

 

 

 

* 파일 가져오기(LOAD DATA INFILE)

-----------------------------------------------------------------------------------------------------------------------------------

외부 파일을 읽기 위해선 시스템변수 변수를 변경해야한다.

SHOW variables LIKE 'local%';

SET GLOBAL loval_infile = 1;

 

"The MySQL server is running with the --secure-file-priv option so it cannot execute this statement"가 뜰 경우

sssunho.tistory.com/56

 

[MySQL] Load Data 시도 중 secure_file_priv 문제 직면

Load Data를 시도하던 중, The MySQL server is running with the --secure-file-priv option so it cannot execute this statement 문제에 직면하였다. 1. MySQL에 접속하여 변수 상태를 확인한다 mysql> SELECT..

sssunho.tistory.com

-----------------------------------------------------------------------------------------------------------------------------------

LOAD DATA INFILE 파일이름 INTO TABLE 테이블이름 옵션설정;

 

CVS외의 텍스트 파일도 읽을 수 있으며, 데이터간의 구분문자와 줄바꿈문자, ~~행부터 읽기 실행 등 읽어들일 데이터의 형식을 지정할 수 있다.

 

FILEDS TERMINATED BY 구분문자 =>기본설정은 \t (탭)

LINES TERMINATED BY 줄바꿈문자 => 기본설정 \n (줄바꿈)

IGNORE 처음에_건너뛸_행 LINES => 기본설정은 0

 

EX)

LOAD DATA INFILE 'C:\test.csv' INTO TABLE tb1N FIELDS

TERMINATED BY ',';

 

tb1N 테이블에 레코드가 추가됨

 

 

 

* 데이터를 텍스트 파일에 내보내기 (export)

내보낸 파일은 다른 데이터베이스나 시스템에서 사용하거나 백업용으로 사용한다.

 

SELECT * INTO OUTFILE '파일이름' 옵션설정 FROM 테이블 이름;

 

옵션 설정은 내보내기할 텍스트 파일의 형식을 지정한다.

ex)

SELECT * INTO OUTFILE 'C:\datat\out.csv' FIELDS TERMINAGETD BY ',' FROM tb1;

 

 

* 데이터베이스 백업/복원

-백업

dump : 데이터베이스의 모든 내용을 추출함

mysqldump 명령을 사용한다.

덤프로 출력된 정보는 일반 sql문으로 되어있는 텍스트이며, 데이터베이스의 모든 정보를 가져올 수 있다.

 

mysqldump -u 사용자이름 -p비밀번호 데이터베이스이름 > 출력파일이름

ex)

mysqldump -u root -p1234 db1 > db1_out.txt

 

-복원

mysqladmin -u 사용자이름 -p비밀번호 데이터베이스이름 < 백업파일이름

ex)

mysqladmin -u root -p1234 db2 < db1_out.txt

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터베이스 예제 2  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
정리  (0) 2021.04.19
트랜젝션  (0) 2021.04.14
SQL JOIN  (0) 2021.03.30
블로그 이미지

아상관없어

,
반응형

* 저장엔진 

  접속기능, SQL문의 내용을 사전에 조사하는 기능 => 상위부분

  상위 부분의 지시를 받아 실제로 검색이나 파일을 조작하는 기능 => 하위 부분 = 저장엔진

  테이블 별로 저장엔진을 지정할 수 있다.

 - 저장엔진확인법

  SHOW CREATE TABLE 테이블이름;

 ENGINE=InnoDB 임을 알 수 있다.

  - 저장엔진 변경

    ALTER TABLE 테이블 이름 ENGINE=엔진이름;

 

 

 

* 트랜젝션

A의 계좌에서 B의 계좌로 10만원을 송금

1. A의 계좌에서 10만원 뺌

2. B의 계좌에 10만원 넣음

 

만약 1번 시점에 오류가 발생하면, 2번이 실행되지 않고 

A의 계좌에서 10만원만 빠지고 그 돈은 사라질 것이다.

따라서 1,2번을 묶어서 하나로 처리한다. 

 

위와 같이 여러 단계의 처리를 하나의 처리처럼 다루는 것이 트랜젝션이다.

트랜젝션의 실행결과를 데이터베이스에 반영하는 것이 Commit이며 

반영시키지않고 되돌리는 것을 RollBack이라 한다.

 

 - 트랜젝션 시작

  START TRANSACTION이나 BEGIN, BEGIN WORK

트랜젝션을 시작하고 tb테이블을 삭제하였다.

이 시점에 테이블의 일부기능에 lock이 걸린다. 

따라서 다른 세션에서 INSERT 등의 명령을 실행할 수 없다.

트랜젝션을 시작한 콘솔창에서 COMMIT이나 ROLLBACK을 해야 다른 명령을 실행 할 수 있다.

ROLLBACK을 하면 삭제된 테이블이 다시 복구되는 것을 알 수 있다.

 

- 자동 커밋 기능

 일반적으로 MYSQL에서 명령을 실행하면 그대로 반영된다.

 명령을 실행하면 그대로 반영되는 기능이 자동 커밋기능이다.

 자동 커밋 기능의 기본 설정은 ON이다.

 자동 커밋 기능을 끄려면

 SET AUTOCOMMIT=0;

 으로 하면 된다.

 

 

 자동 커밋 기능을 끄면 ROLLBACK을 사용할 수 있다.

 SET AUTOCOMMIT=1;

을 하면 다시 자동커밋 기능을 켤 수 있다.

 

자동커밋 기능이 설정되어있는지 확인하려면

SELECT @@AUTOCOMMIT;

을 하면 된다.

0이면 OFF, 1이면 ON

 

트랜젝션을 COMMIT하지 않고 콘솔창을 닫을 경우엔 

트렌젝션을 시작하고 입력한 명령들은 취소된다.

즉, 커밋을 하지 않고 종료하면 그 내용은 파기된다.

 

 

 

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터베이스 예제 2  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
정리  (0) 2021.04.19
파일 사용  (0) 2021.04.14
SQL JOIN  (0) 2021.03.30
블로그 이미지

아상관없어

,

SQL JOIN

공부/데이터베이스 2021. 3. 30. 19:27
반응형

예제용 테이블

- 두개의 테이블 결합

SELECT 칼럼이름

FROM 테이블1

JOIN 결합할테이블2

ON 테이블1의 칼럼 = 테이블2의 칼럼

 

EX) tb의 sales 와 tb1의 name(두 테이블은 공통으로 number를 가짐)

 

SELECT * FROM tb

JOIN tb1 ON tb.number = tb1.number;

(number가 공통값이므로 공통키가됨)

 

- 내부조인

일치하는 레코드만 가져오는 결합

 

EX)

SELECT * FROM tb

INNER JOIN tb1

ON tb.number=tb1.number;

(내부조인을 명시적으로 표시하려면 INNER JOIN으로 사용)

 

- 칼럼을 선택해서 표시

EX)

SELECT tb.number, tb1.name, tb.sales FROM tb

JOIN tb1 ON tb.number=tb1.number;

 

- 테이블 이름이 복잡할 경우 별명을 붙이고 사용

테이블 이름 AS 별명

 

EX)

SELECT x.number, y.name, x.sales FROM tb AS x

JOIN tb1 AS y

ON x.number = y.number;

 

- USING을 사용하여 ON 부분을 알기쉽게 표현

USING(키가 되는 칼럼 이름)을 이요하면 간단하게 표현가능

 

SELECT tb.number, tb1.name, tb.sales FROM tb

JOIN tb1ON tb.number=tb1.number;

            ||

SELECT tb.number, tb1.name, tb.sales FROM tb

JOIN USING (number);

 

- 결합한 테이블에 WHERE 조건 설정

WEHRE 조건을 설정하기 위해선 어느 테이블의 어떤 칼럼인지 명시해야한다.

 

EX) WHERE 테이블.칼럼 > 100

 

EX)tb에서 sales가 100이상 것에 한하여 tb1에서 name을 가져와 표시

SELECT tb.number, tb1.name, tb.sales FROM tb1

JOIN tb USING(number)

WHERE tb.sales >= 100;

 

- 여러 테이블에서 데이터 추출

JOIN할 테이블 수에 제한이 없다.

 

SELECT ~ FROM 테이블이름1

JOIN 테이블이름2 결합조건

JOIN 테이블이름3 결합조건

JOIN 테이블이름4 결합조건

.......

EX)

tb, tb1, tb3는 공통 칼럼 number가 있다.

 

number를 키로 사용하여 number, sales, name, city 를 표시하면

 

SELECT tb.number, tb.sales, tb1.name, tb3.city FROM tb

JOIN tb1 USING(number)

JOIN tb3 USING(number);

 

혹은

 

SELECT tb.number, tb.sales, tb1.name, tb3.city FROM tb

JOIN tb1 ON tb.number=tb1.number

JOIN tb3 ON tb.number=tb3.number;

 

- 외부조인

tb에는 tb1에 존재하지 않는 number 'A107'이 있다. 그리고 tb1에는 tb에 존재하지 않는 'A105'가 있다. 따라서

 

SELECT x.number, y.name, x.sales FROM tb as X

JOIN tb1 as y ON x.number=y.number;

 

할 경우 'A107'과 'A105' 레코드는 표시되지 않는다.

경우에 따라 모든 레코드를 표시해야할 경우에는 외부조인을 사용한다.

 

* 외부 조인의 종류

결합하는 레코드 중 어느 쪽의 레코드를 모두 표시할 것인가에 따라 LEFT JOIN, RIGHT JOIN으로 구분된다.

LEFT JOIN : 일치하는 레코드와 왼쪽 테이블의 모든 레코드를 표시

RIGHT JOIN : 일치하는 레코드와 결합할 오른쪽 테이블의 모든 레코드를 표시

 

- LEFT JOIN

SELECT 칼럼이름 FROM 테이블1

LEFT JOIN 결합할_테이블2 ON 테이블1의 칼럼 = 테이블2의 칼럼;

 

EX)

tb에는 있지만 tb1에는 존재하지 않는 number 'A107' 레코드 표함 표시

(tb, tb1을 number를 키로 LEFT JOIN해서 서로 일치하는 레코드와 tb의 모든 레코드를 표시)

(number와 name 만)

 

SELECT tb.number, tb1.name FROM tb

LEFT JOIN tb1 USING(number);

=> 'A105'는 표시되지 않는다. A107의 name 데이터가 존재하지 않기 때문에 NULL로 표시된다.

 

- RIGHT JOIN

일치하는 레코드와 결합할 오른쪽의 모든 데이터 표시

 

SELECT 칼럼이름 FROM 테이블1

RIGHT JOIN 테이블2(결합할) ON 테이블 1의 칼럼 = 테이블2의 칼럼;

혹은 (USING 칼럼이름)

 

EX)

tb1에는 있지만 tb에는 없는 레코드 표시

tb의 number와 tb1의 name 표시

 

SELECT tb.number, tb1.name FROM tb

RIGHT JOIN tb1 USING(number);

 

- 셀프 조인

자기자신, 같은 이름의 테이블을 결합

같은 이름의 테이블을 결합하므로 같은 칼럼 이름이 2개씩 표시됨

 

SELECT 칼럼이름 FROM 테이블이름 AS 별명1 JOIN 테이블이름 AS 별명2;

 

EX) tb1을 셀프조인하고 모든 칼럼 표시

 

SELECT * FROM tb1 AS a JOIN tb1 AS b;

=> 모든 조합이 생김

모든 조합이 생기기때문에 조건을 설정하여 원하는 것만 선택하면된다.

 

EX) 순위 정하기

RANK와 같은 함수가 없으므로 ORDER나 GROUP 등의 조합으로 처리해야한다.

age 순으로 순위를 매긴다면

 

SELECT a.name, a.age, COUNT(*) AS 'RANK' FROM tb1 AS a

JOIN tb1 AS b

WHERE a.age <= b.age GROUP BY a.number;

WHERE a.age <= b.age GROUP BY a.number => b.age가 a.age 이상인 레코드가 추출된다. 이렇게 추출된 레코드의 개수를 count하면 순위가 된다.

GROUP BY a.number를 하였으므로 A101, A102 ... 모두 비교한다.

A101의 경우 a.age<=b.age가 되는 경우는 첫줄의 경우 밖에 없으므로 count가 1이 된다.

 

- 하위 질의 = 서브쿼리

질의를 실행해서 추출한 데이터를 이용해서 다시 질의를 한다.

하위 질의를 사용하는 처리 대부분은 내부조인등으로 대체 할 수 있다. 하지만 단계별로 처리하는 하위질의를 사용하는것이 더 효율적이다.

 

EX 1)

tb테이블에서 칼럼 sales의 최대값이 잇는 레코드를 표시

 

SELECT * FROM tb WHERE sales IN (SELECT MAX(sales) FROM tb);

=> MAX(sales)인 sales가 있는 레코드를 SELECT 함

 

EX 2)

tb1에서 age 평균값을 계산하고 age가 평균값 이상인 레코드 표시

 

SELECT * FROM tb1 WHERE age>=(SELECT AVG(age) FROM tb1);

 

- 칼럼을 반환하는 하위 질의

SELECT 표시할 칼럼 FROM 테이블 이름

WHERE 칼럼이름 IN (SELECT 이용 하위 질의로 추출한 칼럼)

 

EX)

sales가 200 이상인 name을 표시

SELECT name FROM tb1 WHERE number IN (SELECT number FROM tb WHERE sales>=200);

 

- 하위 질의와 내부 조인의 실행 결과 비교

SELECT number, name FROM tb1

WHERE number IN (SELECT number FROM tb);

 

SELECT tb1.number, tb1.name FROM tb1

JOIN tb ON tb1.number=tb.number;

=> 내부 조인은 tb에 있는 모든 레코드를 표시함

=> 모든 레코드를 표시함

 

* IN 대신에 등호를 사용하면 오류가 발생한다.

 

SELECT * FROM tb1 WHERE number = (SELECT number FROM tb WHERE sales>=200);

-> 하위 질의가 1건 이상 검색되었다라는 오류가 뜸

-> 해당 레코드가 1건 밖에 없을 때에는 등호를 사용해도 오류가 발생하진 않음

-> number가 xx와 정확하게 일치한다라는 조건이면 상관이 없지만, 위 예시는 여러 레코드가 추출되므로 ~중에 어느것 이라는 IN을 사용해야한다.

 

SELECT * FROM tb WHERE number = (SELECT number FROM tb1 WHERE sales>=200 LIMIT 1);

 

이렇게 하면 오류는 뜨진 않지만 A101이 나올지 A102가 나올지 알 수 없어서 결국 LIMIT도 도움이 되진 않는다.

LIMIT로 1건만 추출하기 때문에 오류가 발생하지 않는다.

 

- EXISTS = 존재하는 레코드를 대상으로 검색

EX) tb1에는 tb에 존재하지 않는 number를 가진 레코드도 포함되어있음.

 

SELECT * FROM tb1 WHERE

EXISTS (SELECT * FROM tb WHERE tb.number = tb1.number);

tb에는 A105의 number가 존재하지 않으므로 표시되지 않음

 

- NOT EXISTS 

하위 질의로 추출되지 않는 레코드를 대상으로 함

 

EX)

tb 테이블에 존재하지 않는 레코드의 number만 추출하고 테이블 tb1에서 해당하는 레코드 표시

 

SELECT * FROM tb1

WHERE NOT EXISTS (SELECT* FROM tb WHERE tb.number=tb1.number);

 

 

- 순위 정하기(하위 질의 이용)

1. 연속 번호 기능을 설정한 테이블에 sales의 순서대로 정렬한 레코들 삽입한다.

2. 자동으로 입력되는 연속 번호가 순위가 된다.

 

구체적으로 적으면

1. 테이블 tb와 같은 구조의 테이블 tb_rank를 생성한다.

2. 테이블 tb_rank에 연속번호 기능을 설정한 칼럼 rank를 추가

3. 테이블 tb를 대상으로 sales의 순서대로 SELECT 하는 하위질의를 실행

4. 하위 질의의 결과를 tb_rank에 INSERT

 

1. CREATE TABLE tb_rank LIKE tb;

(tb의 칼럼 구조만 복사하여 tb_rank생성)

2. ALTER TABLE tb_rank ADD rank INT AUTO_INCREMENT PRIMARY KEY;

(tb_rank에 연속번호기능을 설정한 rank 칼럼 추가)

3. INSERT INTO tb_rank (number, sales, month) (SELECT number, sales, month FROM tb ORDER BY sales DESC);

(tb를 sales의 내림차순으로 정렬하고 number, saels, month를 tb_rank에 추가한다.)

728x90
반응형

'공부 > 데이터베이스' 카테고리의 다른 글

데이터베이스 예제 2  (0) 2021.04.20
데이터베이스 예제 1  (0) 2021.04.19
정리  (0) 2021.04.19
파일 사용  (0) 2021.04.14
트랜젝션  (0) 2021.04.14
블로그 이미지

아상관없어

,