Relational DataBase - 3. SQL Basic(1)

SQL

앞서 데이터에 대한 이론적인 조작 방법인 Relational Algebra를 살펴 보았다.
SQL(Structured Query Language)은 이 Relational Algebra를 활용해 실제 Data Base를 다루기 위해 개발된 언어이다.

Relational Algebra는 데이터(Table)를 "어떻게" 다뤄야 할지에 초점을 맞췄었다면, SQL은 이를 바탕으로 DB에게 데이터(Table)을 "이렇게" 다뤄달라고 선언(정의)하는 언어라고 할 수 있다.

( Reational Algebra : Functional Language )
( SQL : Declaritive Language )

즉, SQL은 수행 순서에 관한 것이 전혀 없다는 것을 인지하면서 공부하자.

자료형

Relational Algebra에서 우리가 Attribute를 만들기 위해 Domain이 필요했던 것이 기억나는가?
데이터(Table)을 정의하기에 앞서 이 Domain을 표현하기 위한 대한 약속, 즉 데이터의 자료형을 어떻게 표현할 것인지 알아보고 가자.

  • char(n)
    • n자리 문자열
    • 길이가 고정되어 있기 때문에 주로 문자의 길이가 변하지 않는 데이터를 정의할 때 사용한다.
  • varchar(n)
    • Compact함을 유지하는 n자리 문자열
    • 데이터의 크기에 따라 저장공간의 크기가 변하기 때문에 주로 문자의 길이가 정해지지 않아야 할 때 사용한다.

이 외에도 다음과 같은 다양한 자료형이 존재한다.
(DB마다 다름)

  • int
    • 정수
  • smallint
    • 작은 정수
  • numeric(p,d)
    • 소수점아래 d자리를 갖는 p자리 숫자열
  • float(n) real = float(24) double precision = float(53)
    • 부동 소수점을 사용하는 수 데이터

SQL의 종류

<그림>

1. DDL

Data Definition Language의 약자로 데이터 전체의 골격을 정의할 때 사용하는 문장이다.
즉, Table 자체를 다루는 언어라고 생각하면 된다.

<그림>

이 DDL에는 다음과 같은 명령이 존재한다.

1) Creat

Relation, 즉 table을 만드는 명령어는 다음과 같다.

Table 생성

create table 이름 (
    A1    D1,
    A2    D2,
    A3    D3,
    constraint,
    constraint
);
  1. A: 생성할 Attribute의 이름
  1. D: Attribute의 Domain, 즉, 자료형
  1. constraint: 해당 Attribute의 제약조건

constraint에 대하여

  1. constraint의 종류
    • primary key( A )
    • foreign key( A ) reference r
    • not null
  1. primary key는 반드시 설정해 주어야 한다. (나머지 constraint는 반드시 사용해야 하는것은 아니다.)

(참고: primary key는 unique, not null이 전제조건이다)

  1. constraint의 위치는 Attribute와 같이 쓰거나 아래에 따로 써준다.
    • 아래에 따로 쓸 경우 위와 같이 괄호안에 Attribute 표기
    • Attribute옆에 쓸 경우 그냥 표기

2) Alter

Relation에서 Attribute를 추가하고 삭제하는 명령어는 다음과 같다.

Attribute 추가

alter table r add A D;
  1. r: Attribute를 생성할 Table 이름
  1. A: 생성할 Attribute 이름
  1. D: 생성할 Attribute의 자료형(Domain)

(참고: Attribute를 추가한 후에는 우선 instance는 null값으로 채워짐)

Attribute 삭제

alter table r drop A;
  1. r: Attribute를 삭제할 Table 이름
  1. A: 삭제할 Attribute 이름

(참고: 여러 Table과 얽혀 있는 Attribute를 삭제하는 것은 워낙 까다롭기 때문에 실제 DB에서는 이 기능을 지원하지 않을 가능성이 높다.)

3) Drop

Table 삭제

drop table r;
  1. r: 삭제할 table 이름

2. DML

Data Manipulation Language의 약자로 DDL이 테이블을 대상으로 하는 문장이었다면 DML은 테이블안의 데이터를 다룰 때 사용하는 문장이다.
즉, 데이터베이스에 들어 있는 데이터를 조회하거나 변형(삽입, 수정, 삭제)할 때 사용한다.

<그림>

이 DML에는 다음과 같은 명령이 존재한다.

1) select

우선 데이터(Table)를 조회하고 가져오는 방법부터 알아보자.

이렇게 가져온 데이터들은 Table로 재구성되어 있다. (즉, select의 결과는 Table이다.)

원하는 조건의 Row, Column Select

select Attribute
from Relation
where Condition

Relation안에서 Condition을 만족하는 Row만을 고르고, 그 Tuple들의 Column들 중에서 Attibute에 해당하는 것만 골라내는 명령이다.


  1. select A
    • Relation Algebra의 project와 같은 역할을 수행한다.

(Select 옵션)
select distinct A: 중복 불허한 Tuple들로 Table을 만든다.
select all A : project시 중복 허용, 아무것도 안쓰면 all로 취급
select *: 모든 attribute 보여줌
select salary/12: 가져올 Attribute에 대한 expression 사용 가능


  1. from r
    • r은 데이터를 가져올 Relation의 이름을 의미한다.

(참고: from절에서 사용되는 콤마( , )는 r1과 r2간의 catesian product와 같은 역할을 수행한다.)


  1. where condition
    • Relational Algebra의 select와 같은 역할을 수행한다.

(참고: 사용하지 않으면 보고싶은 데이터의 조건이 없다는 것이므로 모든 데이터를 select한다.)
(자세한 내용은 SQL Basic(2)에서 다뤄보자.)

해석 (수행순서는 존재하지 않지만 해석하는 순서는 존재한다.)
from절의 결과로 얻은 Relation의 Tuple들 중
where조건을 True로 만드는 Tuple들을 골라내어 새로운 Relation을 만든 후
select한 Attrbute만 Projection해서 만든 Relation을 반환한다.

2) delete

원하는 조건의 Tuple 삭제

delete from Relation
where Condition

Relation안에서 Condition을 만족하는 Row들을 골라 삭제하는 명령이다.


  1. delete from r
    • Tuple을 삭제할 Relation 이름
  1. where condition
    • A에 대한 condition을 설정해 삭제할 Tuple을 정한다.

(참고: condition을 안쓰면 테이블 안의 모든 데이터 삭제)
(자세한 내용은 SQL Basic(2)에서 다뤄보자.)

(참고)
1. drop과 delete의 차이점
- drop은 Table을 대상으로 한 명령이다.
- delete는 Tuple을 대상으로 한 명령이다.

2. delete의 순서
delete문은 삭제할 Tuple을 찾자마자 삭제하는 것이 아니라, 모든 Tuple에 대해 삭제할 대상을 찾은 후에 삭제를 실행한다.


따라서 다음과 같은 query를 수행할 때에 avg가 계속 변할 것이라고 생각하여 걱정하지 말자.

delete from instructor
where salary<(select avg(salary) from instructor);

3) insert

그 다음 Table에 한 Tuple을 입력하는 방법은 다음과 같다.

직접 Tuple 입력

insert into Relation(Attribute) values(Tuple);
insert into Relation(Attribute) Relation;

Relation에 Tuple 또는 Table을 추가하는 명령이다.


  1. insert into Relation(A)
    • Tuple을 추가하기를 원하는 Relation 이름

(참고)
((A)를 안쓸 경우: 뒤에 나오는 Tuple은 create에서 생성한 Attribute의 순서대로 나열해 주어야 한다. )
((A)를 쓸 경우: 뒤에 나오는 Tuple은 써준 A의 순서에 맞게 나열해 주면 된다. )

  1. values(Tuple)
    • 넣기를 원하는 Tuple을 나열해 준다
  1. Relation
    • 데이터를 가져올 Relation을 입력해 준다.

(참고)
(이 때, 가져온 Relation의 Attribute의 개수와 자료형은 데이터를 넣을 Relation과 일치해야 한다.)

(예제)

---------------------------------------------------------------------------------
insert into instructor 
         values('10211', null, 'Biology', 66000);
---------------------------------------------------------------------------------
insert into instructor(ID, name, dept_name, salary) 
         values('10211', null, 'Biology', 66000);
---------------------------------------------------------------------------------
insert into student
         select ID, name, dept_name, 0		//0은 student.tot_cred에 넣을 값
         from instructor;
---------------------------------------------------------------------------------
insert into table1 
         select *
         from table2;
---------------------------------------------------------------------------------

4) update

원하는 Tuple의 값 Update

update Relation
  set A = u
  where Condition;

Relation안의 값을 바꾸는 명령이다.


  1. update Relation
    • Update를 원하는 Relation 이름을 입력한다.
  1. set A = u
    • 고른 Tuple의 A라는 Attribute를 u로 바꾼다.

(참고: u에 단일 값을 Return하는 Subquery도 사용할 수 있다.)

  1. condition
    • Update할 Tuple을 고르기 위한 condition을 설정한다.

(해석 순서: update->where->set)

Update 방법을 여러개 설정하고 싶을 때.
1. update문을 여러개 사용한다.

update r
  set A = u
  where condition;
update r
  set A = u
  where condition;

  1. case문을 사용한다.
update r
   set A = case
            when condition then u1
            else u2
           end

(예시)
update student as S
   set tot_cred = (select case
                            when sum(credit) is not null then sum(credits)
                            else 0
                         end
                  from takes natural join course
                  where S.ID=takes.ID and
                        takes.grade != 'F' and
                        takes.grade is not null);

주의
Update문을 중복하여 사용할 경우 원하지 않는 Update를 일으킬 수 있으므로 Update순서를 잘 파악해야 함

update instructor
  set salary = salary*1.05
  where salary <= 100000;

update instructor
  set salary = salary*1.03
  where salary > 100000;

(원했던 동작: 연봉을 100000$을 초과하여 받는 사람들은 연봉을 3%인상하고, 아니면 5%인상하는 것)
(실제 동작: 연봉을 5%인상받은 사람이 인상 후에 100000$초과가 된다면 3%인상을 추가로 받는다)
(위와 아래의 Update순서를 바꿀 경우 문제를 해결 할 수 있다)



DML로 Algebra표현 하기

SQL에 대한 기본적인 구조와 문법은 알았으니, 이제 DML을 활용해 다음과 같은 Algebra는 어떻게 표현할 수 있을 지 생각해 보자.

1. Join

위와 같이 join은 두 Table에서 Attribute의 이름과 그 Instance가 동일한 값을 가질때만 해당 Tuple을 서로 연결하는 Algebra이다.

1) Where절 활용

우선, r x s에서 이름이 같은 Attribute에 대해 같은 값을 가지고 있는 Tuple들을 Select해주는 방법이 있다.

select distinct A, r.B, C, r.D, E
from r, s
where r.B=s.B and r.D=s.D

(주의)
DML은 실제 Algebra와는 달리 기본적으로 r.Bs.B를 같은 Attribute로 보지 않는다.
즉, BD같이 Join하는 Attribute는 select절에서 r또는 s Table중에서 하나만 골라 주어야 한다.

만약 고르지 않을 경우 r.B, s.B, r.D, s.D를 모두 갖는 Table을 얻게 될 것이다.

2) natural Join키워드 활용

그 다음으로 natural join키워드를 활용하는 방법이 있다.

select A, B, C, D, E
from a natural join b

위와 같이 natural join은 이름이 겹치는 Attribute들을 알아서 골라 연결한다.


(참고)
이 때, 1번방법과 달리 Attribute를 연결할 때 알아서 같은 이름의 Attribute중 하나만을 골라 연결하기 때문에 따로 신경쓰지 않아도 된다.

3) Join r using(A)키워드

마지막으로 Join키워드를 사용하는 방법이 있다.

select A, B, C, D ,E
from r join s using(B, D)

본래 natural join은 이름이 같기만 한다면 자동으로 연결했지만, join r using(A)는 using에 사용된 Attribute만을 활용하여 이름이 같을 경우 연결하게 된다.


Join할 때 주의점

  1. where 절
    where을 활용해서 조건에 맞는 Tuple들을 뽑아내어 만든 Relation의 경우 중복이 발생할 가능성이 높다.
    따라서, 이를 잘 파악한 후에 distinct키워드나 다른 조건을 활용하여 중복을 없애자.

  2. natural join
    natural join의 특성상 원하지 않는 Attribute들의 Join이 발생 할 수 있다.
    따라서 다음과 같은 상황을 주의하자.

    • 두 테이블에서 이름이 같은 Attribute가 우연히 있을 경우
      (ex. 이름이 같지만 각 Table에서 뜻을 다르게 사용하고 있을 때)

    • 세개 이상의 Table을 연결할 때
      (ex. a, b, c의 Relation에서 a와 b를 ID로 Join하고 b에 c를 course_id로 Join하고 싶을 때)

      이 경우 Non-Procedural한 Sql의 특성상 a와 b를 join한 후에 그것을 c와 join하는 것이 아니다.
      즉, a와 c에 같은 이름의 Attribute가 있을 경우 a와 c도 join되어 a-b-c 전체가 join이 되어 버린다.

3개를 natural join할 때 발생할 수 있는 문제 예시

아래와 같은 Relation이 3개가 있다고 할 때, 어떤 학생이 어떤 과목을 수강했고, 그 과목의 강의명을 보고싶다고 하자.

즉, 우리는 student와 takes를 ID로 join하고, takes와 course를 course_id로 join해야 한다.

1번방법(잘못됨)

select name, title
from student natural join takes natural join course
// dept_name에 의해 student와 course 또한 join된다  

이 문장은 studenttakes를 join한 후에 그 결과를 course와 join하는 것이 아닌 takesstudent, 그리고 course모두 join 하라는 명령이다.


2번방법

select name, title
from student natural join takes, course
where takes.course_id = course.course_id;
// student와 takes를 join하고 course는 다른 방식으로 join을 했다. 

3번방법

select name, title
from (student natural join takes) join course using course_id
//애초에 course에서 문제가 되었던 dept_name을 빼고, course_id로 join을 했다.

2. Rename

1) Attribute

select절에서 as를 사용할 경우 결과로 만들어 내는 Relation의 Attribute가 Rename되어 출력된다.

select ID, name, salary/12 as monthly_salary
from instructor

(주의)
이 경우, instructor의 salary가 12로 나뉘어 monthly_salary가 되는 것이 아니다.
즉, 이 select의 결과로 나온 Relation에서 Attribute가 monthly_salary로 표현되는 것이다.

2) Table

from절에서 as를 사용할 경우 Table을 Rename하여 사용할 수 있다.

select distinct ID, name
from instructor as T, instructor as b
where T.salary > s.salary;

(참고)
자신의 Relation에서의 데이터와 비교가 필요할 경우가 있다.
이 때 Relation을 Rename하여 활용하면 쉽게 self join을 구현할 수 있고, 자신의 Relation과 비교가 가능해진다.

3) Attribute & Table

from절에서 as와 함께 괄호로 Attribute name을 순서대로 입력해 주면 Table과 그 Attribute 모두 Rename할 수 있다.

select distinct ID, name
from instructor as T(ID, first_name, salary);


Expression

마지막으로 뒤에서 DML의 세부사항을 공부해 보기 전에, SQL로는 다양한 표현들을 어떻게 나타낼 수 있는지 알아보자

들어가기 전에...

1) SQL 논리상태

먼저 SQL에서 논리의 상태는 true, false, Null로 3가지가 존재한다.

여기서 Null이란 값을 모르는 상태라는 뜻을 의미하는데, 만약 연산시 Null이 포함된다면 어떻게 계산해야 할지 유의하면서 다음 연산자들을 살펴보자.

(참고: 상태를 비교할 때에는 비교연산자 =를 사용하면 안되고 is를 사용해 주어야 한다.)
(ex. x=null는 틀린 것, x is null이 맞는 것)

이 부분은 중간에 이해가 가지 않더라도, 일단 "아 이런게 있구나"라는 것만 알아두고 SQL Basic(2)를 본 후 다시 돌아와서 살펴보는 것을 추천한다.

2) Relation의 연산

우선 Relation은 Column과 Row의 개수에 따라 다음과 같이 나눠볼 수 있다.

  • Single Row
    : 하나의 Row와 하나의 Column을 갖는 Relation이다.
  • Multi Row
    : 여러개의 Row와 하나의 Column을 갖는 Relation이다.
  • Multi Column
    : 여러개의 Column을 갖는 Relation이다.

이 때, 이 Relation간의 연산을 어떻게 해야할지 생각해 보자.

  1. 한쪽이 Single Row일 경우

    • 다른쪽도 Single Row일 경우
      : 그냥 값과 값을 비교하면 된다.
    • 다른쪽은 Multi Row일 경우
      : Multi Row의 각 Tuple을 Single Row와 하나씩 비교해 나간다.
  2. 모두 Multi Row일 경우

    • 이 경우에는 우선 원본과 비교 대상을 정해야 한다.
      : 원본의 각 Tuple에 대해 Single Row(원본) - Multi Row(대상) 연산을 하나씩 해 나간다.
  3. Multi Column이 포함된 경우

    • 이 경우에는 Multi Column에서 연산을 원하는 Column을 하나씩 뽑아 연산을 진행한다.
    • 만약 여러 Column의 연산을 원하면 and와 같은 것으로 연결한다.

1. 산술연산, 비교연산

1) 산술 연산자

산술 연산자는 두 값을 더해 결과로 값을 도출하는 연산자이다.

  • Single-Row 산술연산
    대상: 산술 대상이 Single-Row일 경우 사용할 수 있다.

(만약 A와 X가같은 Table에 있는 경우라면 X에 Attribute가 들어 갈 수 있다.)


(참고: Null의 판단)
null + 2000 = null

2) 비교 연산자

비교 연산자는 두 대상을 비교하여 결과로 논리 상태를 도출하는 연산자이다.

  • Single-Row 비교연산
    대상: 비교 대상 중 하나가 Single-Row일 경우에만 사용할 수 있다.

(마찬가지로 A와 X가같은 Table에 있는 경우라면 X에 Attribute가 들어 갈 수 있다.)

(참고: Tuple을 이용하면 =연산자를 좀더 쉽게 사용할 수 있다.)
(ex. A=a and B=b and C=c = (A, B, C)=(a, b, c)이다.)


  • Multi-Row 비교연산
    대상: 비교 대상 모두 Multi-Row일 경우 다음과 같은 방법으로 비교할 수 있다.

(비교 연산자와 위의 논리 연산자를 활용하면 다중행과 다중행을 비교할 수 있다.)


(참고: Null의 판단)
null > 2000 = null

3) 문자열 비교 연산자

  • 문자열과 문자열 비교

(참고: % 키워드는 연산양이 많아 대용량 db에서 사용할 경우 시간이 오래걸릴 수 있다.)


2. 논리연산

1) 논리 연산자

다음의 연산자는 주로 앞의 논리와 뒤의 논리를 연결해 주는 역할을 한다.

(참고: between은 폐구간 범위를 만들어 준다.)


(참고: Null의 판단)
null or true = true
null or false = null
null or null = null

null and true = null
null and false = false
null and null = null

not null = null

2) 논리 연산자2

다음의 연산자는 주로 Relation과 Relation간에 비교를 할 때 사용하는 논리 연산자들이다.

multi-row, multi-column 상관없이 사용

(참고: 위에서 본 all, some 또한 여기에 포함되는 논리 연산자이다.)
(참고: in은 Element와 Relation의 포함관계를 조사할 때, exist는 Relation과 Relation의 포함관계를 조사할 때 사용한다. )


3. 집합연산

다음의 연산자들은 서로 다른 Table들을 다룰 수 있는 연산자이다. (multi-row, multi-column 상관없이)

1) 집합 연산자

multi-row, multi-column 상관없이 사용

(주의)
집합 연산은 Tuple을 합치는 것이기 때문에 rs는 같은 Attribute들을 가지고 있어야 한다.


(참고: set과 multi-set)

  1. set
    • 집합은, 중복된 값(Tuple)이라면 하나의 값(Tuple)으로 취급한다.
    • ex. {a, b, c, c} = {a, b, c}
  1. multi-set
    • multi-set은 중복된 값(Tuple)이라고 하더라도 그 개수까지 해당 set의 하나의 특징으로 취급한다.
    • ex. {a, b, c, c} <> {a, b, c}

즉, set operation의 결과는 중복을 제거하고 나타나지만 multi-set operation의 결과는 중복을 제거하지 않고 나타난다.



좋은 웹페이지 즐겨찾기