ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Introduction to SQL
    데이터 베이스 시스템 2022. 4. 4. 20:14
    728x90

    SQL Parts

    sql은 크게 DML과 DDL로 나뉩니다.

    DML : 데이터베이스에서 정보를 물을 수 있고, tuple을 삽입, 삭제 및 수정할 수 있는 기능이 있습니다.

    integrity : DDL에는 무결정 제약 조건을 지정하는 명령이 포함되어 있습니다.

    View definition : DDL에는 view를 정의하는 명령어가 포함되어 있습니다.

    Transaction control : transaction의 시작과 종료를 지정하는 명령어가 포함되어 있습니다.

    Embeded SQL and dynamic SQL : 일반적인 프로그래밍 언어에 sql문을 삽입하는 방법을 정의합니다.

    Authorization : relation 및 view에 대한 access 권한을 지정하는 명령이 포함되어 있습니다.

     

    Data Definition Language (DDL)

    DDL을 사용하면 다음과 같은 relation에 대한 정보를 지정할 수 있습니다.

    • 각 relation의 schema
    • 각 attribute와 관련된 값의 유형
    • 무결성 제약조건
    • 각 relation에 대해 유지되는 인덱스 집합
    • 각 relation에 대한 보안성과 권한성
    • disk에 있는 각 relation의 물리적인 저장 구조

    Domain Types in SQL

    char(n) : 길이가 n으로 고정된 문자열

    varchar(n) : 최대 길이가 n이 가변적인 문자열

    ex) n = 5 이고 문자열이 "adv" 라면 char(5) = adv_ _ 입니다. char은 무조건 길이가 n으로 고정되기 때문에

    문자열의 길이가 부족하면 뒤에 space를 붙여 n으로 만들어줍니다.

    varchar(5) = adv 입니다.

     

    int : 정수

    smallint : 작은 정수

    numeric(p, d) : 전체 자리수가 p 이고 소숫점 아리자리수가 d인 실수 입니다.

    ex) numeric(3, 1)이면 44.5(o), 3.12(x), 444.5(x)

    real, double, precision 

    float(n) : 사용자가 지정한 정밀도가 n자리 이상인 부동 소수점 

     

    Create Table Construct

    create table r
      (A1 D1, A2 D2, ... , An Dn, (integrity-constraint1), ... , (integrity-constraintk));

    처음에 table을 생성하는 명령어는 create table입니다.

    r은 relation의 이름입니다.

    각각의 A1, A2, ...An은 r의 schema에 있는 attribure의 이름

    D1, D2, ...Dn은 A1, A2, ....An의 data type입니다.

     

    ex)

    create table instructor (
        ID           char(5),
        name         varchar(20),
        dept_name    varchar(20),
        salary       nuumeric(8,2));

     

    Integrity Constraints in Create Table

    무결성 제약조건의 종류

    • primary key (A1, A2, ....An)
    • foreign key (Am, ..., An) references r
    • not NULL

    등등

    create table instructor (
        ID          char(5),
        name        varchar(20) not null, 
        dept_name   varchar(20), 
        salary      nuumeric(8,2), 
        primary key(ID), 
        foreign key(dept_name) references department);

    SQL는 데이터베이스에서 일어난 Update가 무결성제약조건에 위반하지 않게 막아줍니다.

     

    ex) relation 정의에 대한 여러가지 예시

    create table student (
         ID            varchar(5),
         name          varchar(20) not null,
         dept_name     varchar(20),
         tot_cred      numeric(3,0),    
         primary key    (ID),
         foreign key    (dept_name) references department);
    create table takes (
        ID                 varchar(5),
        course_id          varchar(8),
        sec_id             varchar(8), 
        semester           varchar(6),
        year               numeric(4,0),
        grade              varchar(2),
        primary key (ID, course_id, sec_id, semester, year) , 
        foreign key (ID) references student,
        foreign key (course_id, sec_id, semester, year) references section) ;
    create table course (
        course_id         varchar(8),
        title             varchar(50),            
        dept_name         varchar(20),
        credits           numeric(2,0),
        primary key     (course_id),
        foreign key     (dept_name) references department) ;

     

    Updates to tables

    Insert

    relation에 tuple을 집어넣습니다. ex('10211', 'Smith', 'Biology', 66000) 삽입

     

    Delete

    relaiton에 있는 모든 tuple을 지웁니다.

     

    Drop Table

    relation 자체를 지웁니다 (relation의 tuple을 모두 삭제한후 drop가능)

     

    Alter (주의해서 사용해야함)

    데이터베이스의 schema를 바꿉니다.

    1) alter table r add A D

    attribute를 추가하는 것입니다.

    A는 relation r에 추가된 attribute의 이름이고 D는 A의 domain입니다.

    relation에 있는 모든 기존의 tuple은 null이 새 attribute의 값으로 할당 됩니다.

    2) alter table r drop A (가급적 사용금지)

    attribute를 삭제 합니다.

    A는 relation r의 attribute이름입니다.

    많은 데이터베이스에서 attribute 삭제가 지원되지 않을 수 있슶니다.

     

    Basic Query Structure

    전형적인 SQL query는 아래와 같습니다.

    select A1, A2 , ... , An
    from r1, r2, ... , rm
    where P;

    Ai 는 attribute를 나타냅니다.

    ri 는 relation을 나타냅니다.

    P는 predicate를 나타냅니다. 즉, 조건같은것이라고 생각합니다.

     

    SQL query의 결과값은 항상 relation입니다.

     

    The select Clause

    select는 query 결과의 attribute를 나열해서 나타냅니다.

    projection operation과 동일합니다.

    예를 들어 instructor relation의 모든 instructor 이름을 찾고 싶으면

    select name
    from instructor;

    위 SQL에서 name, instructor은 대소문자를 구별안합니다.

    NAME = name = Name

     

    SQL은 query결과 뿐 만아니라 relation 안에서의 중복을 허용합니다.

    따라서 중복되는 값을 제거하려면 select 뒤에 'distinct'라는 값을 적어줘야합니다.

    select distinct dept_name
    from instructor;

    반면에 select뒤에 'all'을 입력하면 중복되는 값도 포함해서 모두 보여줍니다.

    select all dept_name
    from instructor;

    가장 왼쪽에 있는 것은 select dept_name

    가운데는 select distinct dept_name

    오른쪽은 select all dept_name

     

    select뒤에 *을 붙여주면 all attribute를 보여줍니다.

    select *
    from instructor;

    위의 SQL을 적어주면 instructor의 table 전체를 가져옵니다.

    select문까지 쓰고 from문을 안쓸 수 있습니다.

    select '437'

    437의 값을 갖는 열과 한개의 행으로 이루어진 table이 나옵니다.

     

    열에다가 이름을 설정할 수 있습니다.

    열의 이름을 FOO라고 하고 싶다면 as문을 사용합니다.

    select '437' as FOO

    select 'A'
    from instructor

    위의 SQL을 입력하면 한개의 열과 instructor table이 가지고 있는 행의 개수만큼 A가 채워집니다.

    select문에는 +, -, *, / 와 같은 연산자를 쓸 수 있습니다.

    select ID, name, salary/12
    from instructor;

    as문을 써서 salary/12를 monthly_salary로 바꿀 수 있습니다.

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

     

    The where Clause

    where절은 조건을 지정해줍니다. 

    relational algebra에서 selection predicate와 동일합니다.

     

    depart_name이 Comp. Sci인 모든 instructor을 찾고싶으면 (Comp. Sci. 학과에 있는 모든 교수이름)

    select name
    from instructor
    where dept_name = 'Comp. Sci';

    SQL에는 논리연산자도 이용가능합니다. and, or, not

    또한 비교연산자도 이용가능합니다. <, <=, >, >=, =, <>(같지 않다)

     

    Comp. Sci. 학과에 연봉이 70000이 넘는 교수이름을 알고싶으면

    select name
    from instructor
    where dept_name = 'Comp. Sci.' and salary>70000;

    The from Clause

    from 뒤에 여러개의 relation이 올 경우, 이는 relation algebra의 Cartesian product와 같습니다.

    instructor X teaches를 구하고 싶으면

    select *
    from instructor, teaches;

    .

    .

    .

    이 때 공통적인 attribute가 있는 경우 (relation name.attribute name)으로 이름이 재정의 됩니다.

    위에서는 instructor와 teach relation에 공통적으로 ID가 겹칩니다.

    ex) instructor.ID

    Cartesian priduct는 직접쓰기에는 별로지만 where clause와 함께 쓰면 굉장히 유용합니다.

    ( = join operation)

     

    Example

    1) 현재 실제로 course를 가르치고 있는 교수자의 이름과 그 course_id를 찾기

    select name, course_id
    from instructor, teaches
    where instructor.ID = teaches.ID;

    2) Music department에 있고, 현재 실제로 가르치고 있는 교수자의 이름과 그 course_id찾기

    select name,course_id
    from instructor,teaches
    where instructor.ID = teaches.ID and instructor.dept_name = 'Music'

    The Rename Operation

    SQL은 relation과 attribute를 as 구문을 이용해서 이름을 재정의 할 수 있습니다.

    old-name as new-name

     

    ex) 컴퓨터 학과 교수보다 더 높은 연봉을 받는 모든 교수의 이름을 찾아라

    select distinct T.name
    from instructor as T, instructor as S
    where T.salary > S.salary and S.dept_name = 'Comp.Sci.`

     

     

    ex) loan_number loan_id 개명하여 고객의 이름, loan number, amount 구하는 질의는 다음과 같습니다.

    select customer_name, loan_amount as loan_id, amount
    from borrower, loan
    where borrower.loan_number = loan.loan_number

    as는 생략이 가능합니다.

    ex) instructor as T == instructor T

     

    Self Join Example

    relation E 입니다.

    여기서 "BoB"의 supervisor의 supervisor의 supervisor의 ... 를 찾으라 하면 (BoB -> Alice -> David)

    select *
    from E as e1, E as e2
    where e1.supervisor = e2.supervisor

     

    String Operations

    SQL은 문자열을 비교하는 string-matching operator를 가지고 있습니다.

    문자열 패턴은 2가지 특수 문자를 사용하여 나타냅니다.

    1. 퍼센트(%) : 이것은 길이가 0이상인 모든 substring에 해당됩니다.

    2. 언더스코어(_) : 이것은 하나의 문자에 해당됩니다.

    패턴은 대소문자를 구분합니다.

     

    ex) 모든 교수중에 이름에 "dar"이 들어가는 이름을 모두 찾아라

    select name
    from instructor
    where name like '%dar%';

    만약 substring이 "100%" 라면

    like '100\%' escape '\'

    라고 작성합니다. 

    만약 문자열이 처음에 Intro로 시작한다면

    where name like 'Intro%'

    라고 작성합니다.

    만약 3개의 문자로 이루어진 문자열을 찾고 싶다면

    where name like '_ _ _'

    라고 작성합니다.

    만약 3개 문자 이상의 문자열을 찾고 싶다면

    where name like '_ _ _%'

    라고 작성합니다.

     

    SQL은 다음과 같은 다양한 string operation을 제공합니다.

    concatenation (using ||) : 이어 붙이기

    converting from upper to lower case : 대문자에서 소문자로 변환, 또는 그 반대

    finding string length, extracting substring etc : 문자열 길이 찾기, substring 추출 등

     

    Ordering the Display of Tuples

    예를 들어 교수들의 이름을 알파벳 순서로 정렬하고 싶을 경우 order by 를 쓸 수 있습니다.

    select distinct name
    from instructor
    order by name

    또한 내림차순(desc), 오름차순(asc)도 지정 가능합니다. (기본적으로 오름차순으로 되있습니다)

    select distinct name
    from instructor
    order by name desc

    또한 여러 attribute를 기준으로 정렬할 수 있습니다.

    select distinct name
    from instructor
    order by dept_name, name

     

    Where Clause Predicates

    SQL에서는 where절에서 사용할 수 있는 비교 연산자로서 between을 포함하고 있습니다.

    이 절은 어떤 값보다 크거나 같고, 다른 어떤 값보다 작거나 같다는 것을 나타냅니다. 

     

    예를들어 90000달러 이상 100000달러 이하인 loan amount를 갖는 모든 loan을 구하려고 하면

    select name
    from instructor
    where salary between 90000 and 100000

     

    Tuple comparison

    예를 들어 instructor ID가 teaches ID와 같고 dept_name이 Biology인 교수의 이름과 course_id를 구하려고하면

    select name, course_id
    from instructor, teaches
    where (instructor.ID, dept_name)=(teaches.ID, 'Biology');

     

    Set Operations

    Union (합집합)

    ex) 2017년 가을 학기와 2018년 봄학기에 열린 모든 강의들의 강의 번호 구하기

    (select course_id from section where semester='Fall' and year = 2017)
    union
    (select course_id from section where semester='Spring' and year = 2018);

    Intersect (교집합)

    2017년 가을학기 그리고 2018년 봄학기에 열린 강의들의 강의 번호 구하기

    (select course_id from section where semester='Fall' and year = 2017)
    intersect
    (select course_id from section where semester='Spring' and year = 2018);

    Except (차집합)

    2017년 가을 학기에 열리고 2018년 봄학기에 안 열린 강의들의 강의 번호 구하기

    (select course_id from section where semester='Fall' and year = 2017)
    except
    (select course_id from section where semester='Spring' and year = 2018);

     

    기본적으로 Set Operation들은 중복을 제거합니다.

    만약 중복을 보존하고 싶으면

    union all

    intersect all

    except all

    을 사용하면 됩니다.

     

    Null Values

    tuple들을 전부 null 값으로 채울 수 있습니다.

    null은 알 수 없는 unknown 값 또는 존재하지 않는 값을 나타냅니다.

    null을 포함하는 산술식의 결과는 항상 null입니다. ex(5 + null = null)

    is null을 활용해 null 값인지를 체크할 수 있습니다.

    ex) 모든 교수중에 salary가 null인 것을 찾아라

    select name
    from instructor
    where salary is null;

    is not null은 null 값이 아닐 경우 true입니다.

    null 값이 비교 구문에 포함될 경우 unknown을 return합니다.

    ex) 5 < null 또는 null <> null 또는 null = null (모두 null을 return 합니다.)

     

    where의 술어부분에서는 Boolean operation이 작동하므로 unknown이 끼어있을 때 어떻게 할지 결정해야합니다.

    and : (true and unknown) = unknown

           (false and unknown) = false

           (unknown and unknown) = unknown

    or : (unknown or true) = true

         (unknown or false) = unknown

         (unknown or unknown) = unknown

     

    where 구문에서 unknown으로 판명될 경우 false로 취급합니다.

     

    Aggregate Functions

    집계 함수

    SQL에서는 다음과 같은 함수들을 제공합니다.

    avg : 평균값

    min : 최솟값

    max : 최댓값

    sum : 합

    count : (number of values) 개수 세기

     

    ex) 컴퓨터학과 교수의 평균 급여

    select avg(salary)
    from instructor
    where dept_name = 'Comp. Sci.';

    ex) 2018년 봄학기에 가르친 모든 교수들의 수

    select count (distinct ID)
    from teaches
    where semester = 'Spring' and year=2018;

    ex) course relation안에 있는 모든 tuple의 개수

    select count (*)
    from course;

     

    group by : 동일한 값끼리 묶어서 보여줍니다.

    ex) 각 학과의 교수님들의 평균 salary

    select dept_name, avg (salary) as avg_salary
     from instructor
     group by dept_name;

    왼쪽의 table로 부터 오른쪽 table의 결과가 return됩니다.

     

    group by 함수를 사용하려면 반드시 select에 존재해야 합니다.

    ex) 다음은 error query입니다.

    select dept_name, ID, avg(salary)
    from instructor
    group by dept_name;

    select문에 ID가 들어가게 되면 하나의 속성으로 통일 불가

     

    having

    예를 들어 평균 salary가 42000보다 큰 모든 과를 찾아서 이름과 평균 salary을 보여주어라

    select dept_name, avg (salary) as avg_salary
    from instructor
    group by dept_name
    having avg (salary) > 42000;

    대충 보면 where과 사용이 매우 비슷하지만, where절의 술어는 group을 형성하기 전에 적용되고,

    having 절의 술어는 그룹을 형성한 이후 적용됩니다. 

    만약 where절을 썼다면 전체 과 교수님의 평균에 대해 계산했을 것입니다. 

    having 절을 썼기 떄문에, 먼저 그룹화 한 이후 그룹 평군에 대해 계산하여 보여줄 수 있는것입니다.

     

    Nested Subqueries

    중첩 query입니다.

    즉, 다른 쿼리 내에 쿼리를 중첩해서 쓰는것입니다.

    subquery란 다른 쿼리 안에 중첩되어 있는 select-from-where 구문을 말합니다.

     

    기존 기본 query

    select A1, A2, ... ,An
    from r1, r2, ... , rm
    where P;

    From clause : ri는 어느 valid subquery로도 대체될 수 있습니다.

    Where clause : P는 다음과 같은 형식으로 대체될 수 있습니다. 

                        B<operation>(subquery) : B는 attribute이고 <operation>은 나중에 선언된것입니다.

    Select clause : Ai는 어떤 single value를 만들어내는 subquery라면 대체될 수 있습니다.

     

    Set Membership

    ex) 2017 가을과 2018년 봄에 둘다 열린 course 찾아라 (in)

    select distinct course_id
    from section 
    where semester = 'Fall' and year=2017 and 
          course_id in (select course_id 
                        from section 
                        where semester= 'Spring' and year = 2018);

    Union을 사용하면 다음과 같습니다.

    (select course_id from section where sem='Fall' and year = 2017)
    union
    (select course_id from section where sem='Spring' and year = 2018);

    ex) 2017년 가을에는 열렸지만 2018년 봄에는 열리지 않는 course 찾아라 (not in)

    select distinct course_id
    from section
    where semester = 'Fall' and year=2017 and
          course_id not in (select course_id
                            from section
                            where semester='Spring' and year = 2018);

    except(차집합)을 사용하면 다음과 같습니다.

    (select course_id from section where sem='Fall' and year = 2017)
    except
    (select course_id from section where sem='Spring' and year = 2018);

    ex) 교수의 이름이 "Mozart"도 아니고 "Einstein"도 아닌 instructor의 이름 찾기 (not in)

    select distinct name
    from instructor
    where name not in ('Morzart', 'Einstein');


    ex) ID 10101을 가진 교수한테 강의를 듣는 학생의 총 수를 찾아라 (in)

    select count (distinct ID)
    from takes
    where (course_id, sec_id, semester, year) in
                        (select course_id, sec_id, semester, year
                         from teaches
                         where teaches.ID=10101);

     

    ID가 10101인 교수의 수업 id, 분반, 학기, 년도를 가져와서 그 해당 수업을 듣는 학생의 ID를 세는 방식입니다.

     

    위의 query들은 훨씬 더 간단한 방법으로 작성할 수 있습니다.

    위의 공식은 단순히 SQL의 기능을 설명하기 위한것입니다.

     

    Set Comparison - "some" Clause

    some (= or)

    ex) biology 학과에 있는 교수 중 아무나 한 명보다 자신의 salary가 더 큰 사람의 이름을 구하라

    즉, biology 학과에 있는 교수의 salary 중 가장 낮은 salary보다 자신의 salary가 큰 사람

    select distinct T.name 
    from instructor as T, instructor as S
    where T.salary > S.salary and S.dept_name = 'Biology';

    some 구문을 사용해 똑같이 구현가능합니다.

    select name
    from instructor
    where salary > some (select salary
                         from instructor
                         where dept_name='Biology');

     

    F<comp> some r => ex) 5 < some 0, 5, 6 = true

    0, 5, 6 중에 한개라고 5보다 크면 true입니다.

     

     

     

     

     

     

    5랑 같은게 1개라도 있으면 true

     

     

     

    5랑 같지 않은게 1개라도 있으면 true

     

     

    Set Comparison - "all" Clause

    all (= and)

    ex) biology 학과에 있는 모든 교수의 salary 보다도 더 큰 salary를 받는 instructor 이름을 찾아보자

    즉, biology 학과에 있는 교수의 salary 중 가장 큰 salary보다도 자신의 salary가 더 큰사람

    select name
    from instructor
    where salary > all(select salary
                       from instructor
                       where dept_name = "Biology");

    모든 수가 5보다 커야 true

     

     

     

     

     

     

     

    모든수가 5와 같아야 true

     

     

     

    모든 수가 5와 달라야 true

     

     

     

    some ==in

    !all = not in

    !some != not in 이고 all != in 입니다.

     

    exists clause

    exists는 해당 subquery가 nonempty이면 true를 return합니다.

    not exists는 해앙 subquery가 empty이면 true를 return합니다.

     

    ex) 2017년 가을 학기와 2018년 봄 학기에 모두 열린 과목을 exist구문을 사용해 구현하면

    select course_id
    from section as S
    where semester = 'Fall' and year = 2017 and
        exists (select * 
                from section as T
                where semester = 'Spring' and year = 2018
                      and S.course_id = T.course_id) ;

    section을 S로 불러와서 S 안에서 2017 가을에 열리는 과목을 찾아두고

    section을 다시 T로 불러와서 그 T안에서 2018 봄에 열리고, 2017 가을에 열린 그 과목 course_id와 같은게 

    있는지 찾아봅니다.

    같은게 있다면 그 과목은 두번 다 열린게 맞으므로 course_id 반환합니다.

     

    not exists clause

    ex) biology 학과에서 열리는 모든 과목을 들은 학생을 찾아라

    일단 strudent table에서 이름을 가져옵니다.

    student table에서 사람 한 명을 선택한 상태라고 가정합니다.

    이 사람에 대해서 where절을 검사해줍니다. 차집합을 해줄건데 먼저 biology 학과에서 열린 모든 과목 course_id를

    가져 옵니다. 그다음 이 course_id 집합에서 지금 선택한 학생이 듣고 있는 수업을 아래 select절을 통해 구해서

    빼줍니다.

    그러면 이제 biology 학과에서 열린 과목 중 학생이 듣지 않은 수업만이 남아 not exists 로 갑니다.

    만약 이떄 not exists가 공집합이라면 모든 과목을 다 들었다는 의미이므로 not exists가 true가 되어 

    해당 student를 return해줍니다.

     

    Test for Absence of Duplicate Tuples

    subquery에 중복된 tuple이 있는지 여부를 검사하여 중복이 없을 경우 true을 return합니다.

     

    ex) 2017년에 기껏해야 한 번 열린 모든 과목을 찾아라

    select T.course_id
    from course as T
    where unique ( select R.course_id
                    from section as R
                    where T.course_id = R.course_id
                          and R.year = 2017);
    select T.course_id
    from course as T
    where 1>= ( select count(R.course_id)
                    from section as R
                    where T.course_id = R.course_id
                          and R.year = 2017);

     

    Subquries in the From Clause

    sql은 from문에서 subquery를 허용합니다.

     

    ex) 평균 연봉이 $42,000 보다 더 큰 과들의 평균 연봉을 구하라

    select dept_name, avg_salary
    from (select dept_name, avg (salary) as avg_salary
          from instructor
          group by dept_name)
    where avg_salary > 42000;

    위의 경우 having을 쓸 필요가 없습니다. from 안의 절이 먼저 처리가 됩니다.

    다른 방식으로 결과를 table화 할 수 도 있습니다. (from ~ as 이용)

    select dept_name, avg_salary
    from (select dept_name, avg (salary)
          from instructor
          group by dept_name)
          as dept_avg (dept_name, avg_salary)
    where avg_salary > 42000;

     

    With Clause

    query 안에서 임시로 작동하는 임시적인 table을 만듭니다. 

     

    ex) 가장 많은 예산을 가진 모든 department를 찾아라

    with max_budget(value) as 
        (select max(budget) 
         from department) 
    select dept_name
    from department, max_budget 
    where department.budget = max_budget.value;

     

    ex) 총 급여가 모든 부서의 총 급여의 평균보다 큰 부서를 찾아라

    with dept_total (dept_name, value) as
        (select dept_name, sum(salary)
        from instructor
        group by dept_name),
    dept_total_avg(value) as
        (select avg(value)
        from dept_total)
    select dept_name
    from dept_total, dept_total_avg
    where dept_total.value>dept_total_avg.value;

    dept_name과 부서의 salary의 총 합을 저장하고 있는 dept_total이라는 table과 dept_total의 value

    즉, 각 부서별 salary의 총 합을 평균낸 값을 저장하고 있는 dept_total_avg를 새로 만듭니다.

    그리고 이 두 table에서 value값을 비교해 부서를 찾습니다.

     

    Scalar Subquery

    결과값이 하나일 것으로 예상될 때 사용합니다.  select에 쓸 수 있습니다.

    ex) 모든 부서를 각 부서의 교수자의 수와 함께 열거해라

    select dept_name,
            (select count(*) //1 개의 속성을 가진 tuple (여기서는 숫자)
           from instructor
           where department.dept_name = instructor.dept_name)
         as num_instructors
    from department;

    만약 suquery가 한개 이상의 tuple을 return할 경우 runtime error가 발생합니다.

     

    Modification of the Database

    Deletion, Insert, Update의 기능이 있습니다.

     

    Deletion

    모든 tuple을 다 지울 경우

    delete from instructor

    tuple중 특정 조건을 만족하는 tuple만 지울 경우

    delete from instructor
    where dept_name = 'Finance';

     

    ex) Watson building에 위치한 아파트에 사는 instructor을 지워라

    delete from instructor
    where dept_name in (select dept_name 
                        from department
                        where building = 'Watson');

     

    ex) 연봉이 평균 연봉보다 작은 사람들을 지워라

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

    이 경우 평균을 매번 구하게 되면 delete 할때 마다 기준이 되는 평균값이 달라질 수 있습니다. 

    따라서 평균값을 먼저 구해 값을 고정한 다음에 delete할 대상을 찾아봅니다. 

    그 다음 delete할 대상을 한번에 지웁니다. (avg를 다시 계산하거나 비교를 다시 하지 않습니다.)

     

    Insertion

    새로운 tuple을 삽입합니다.

    insert into course
        values('CS-437', 'Database Systems', 'Comp.Sci.', 4);

    또는 

    insert into course(course_id, title, dept_name, credits)
        values('CS-437', 'Database Systems', 'Comp.Sci.', 4);

     

    만약 일부 항목을 빈칸으로 채우고 싶으면

    insert into student 
       values ('3003', 'Green', 'Finance', null);

    위와 같이 null을 적어줍니다.

     

    ex) 144학점 이상 들은 음악과에 있는 학생들을 연봉 18,000인 교수로 추가해라

    insert into instructor  
    select ID, name, dept_name, 18000  
    from student  
    where dept_name = 'Music' and total_cred>144;

    select, from, where 문은 relation에 삽입되기 전에 다 계산이 완료됩니다. 그리고 그 결과를 삽입하는 것입니다.

    그렇지 않으면 다음 query를 수행할 때 문제가 생깁니다.

    insert into table1 select * from table1; //무한 루프

     

    Updates

    몇몇 요소들을 update합니다.

     

    ex) 모든 교수들의 연봉을 5% 인상

    update instructor  
      set salary = salary * 1.05;

    ex) 70000 보다 적게 버는 교수 5% 연봉 인상

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

    ex) 평균보다 낮은 교수 연봉 5% 인상

    update instructor  
    set salary = salary * 1.05  
    where salary<(select avg(salary)  
                  from instructor);

    ex) 100000이 넘는 사람은 3%인상하고 나머지는 5%인상

    update instructor  
      set salary = salary * 1.03  
      where salary > 100000;  
      
    update instructor  
      set salary = salary * 1.05  
      where salary <= 1000000;

    두 개의 update 문을 사용할 수 있습니다. 첫번째 update문을 먼저할지 두번째 update문을 먼저할지 에 따라

    결과가 다르게 나옵니다. 따라서 순서가 중요합니다.

     

    이를 개선한것이 case문입니다.

    update instructor  
    set salary = case  
                   when salary <= 100000 then salary * 1.05  
                   else salary * 1.03  
                 end;

    일반적으로 case문을 사용하는것이 더 좋습니다.

     

    case문의 템플릿입니다.

     

    Updates with Scalar Subqueries

    tot_creds 의 값을 재계산 및 update

    update student 
    set tot_cred = (select sum(credits)  
                    from takes, course  
                    where takes.course_id = course.course_id and  
                          student.ID = takes.ID and  
                          takes.grade<>'F' and  
                          takes.grade is not null);

    만약 어떠한 course도 수강하지 않은 학생은 tot_creds를 null값으로 설정하려면 다음 코드를 sum(credits) 대신 사용

    case  
      when sum(credits) is not null then sum(credits)  
      else 0  
    end

     

    '데이터 베이스 시스템' 카테고리의 다른 글

    Normalization  (0) 2022.05.02
    Intermediate SQL  (0) 2022.04.16
    Database Design Using the E-R Model  (0) 2022.04.02
    Intro to Relation Model  (0) 2022.03.20
    Introduction  (0) 2022.03.07
Designed by Tistory.