1. 무결성 관리

 

👩🏻‍💻 모든 데이터가 결함없이 완벽한 상태를 무결성 Intergrity 이라고 함

 

  📍 시스템이 완벽해도 무결성이 깨지는 경우가 종종 발생

        ➡️수나 에러로 잘못된 데이터를 입력할 수도 있고 불가항력적인 요인으로 멀쩡하던 데이터가 파괴되기도 함

  📍 무결성이 깨지면 데이터를 사용하는 응용 프로그램도 제대로 돌아가지 x

 

 

    🔎  예를 들어 컴퓨터 부품을 파는 쇼핑몰의 주문 테이블을 살펴보자

 

// 날짜 회원 제품 개수
2020-03-04 가희원 하이넥스 메모리 DDR 64G 2
2020-03-09 나종원 엘지 그램 노트북 15 32767
2042-12-25 다민기 ATI 그래픽 카드 -8242
2020-04-01 라진규 NULL 3

  📍 첫 번째 레코드만 정상이고 이후의 레코드는 이상해 보임

        ➡️ 나종원의 노트북 32,767개는 정상 주문으로 보기 힘들고,

             다민기의 경우 주문날짜도 2042년이고 주문 개수도 음수

             라진규는 주문한 제품의 이름을 입력하지 않았음.

 

 

👩🏻‍💻  무결성이 깨지는 원인은 다양. 디스크가 기계적으로 손상되거나 네트워크의 불안정으로 데이터가 손실되는 경우, 가장 큰 원인은 사람의 실수

👩🏻‍💻  발생 가능한 모든 오류에 대처하는 방어 체계로 데이터를 처리하는 단계별로 서버측과 클라이언트측이 각자의 무결성 관리 정책을 제공

  📍 '클라이언트측'에서는 입력할 정보에 꼭 맞는 컨트롤로 오입력을 원천 차단, 유효한 값만 서버로 보냄.

  📍 '서버측'의 무결성 처리는 DBMS가 규칙을 기억하고 있다가 비정상 데이터의 입력을 거부하는 방식

 

 

[ 적용 범위에 따른 무결성 구분 ]

 *  컬럼 무결성 컬럼 하나에 저장되는 원자적인 값을 점검하며 도메인 무결성이라고도함
      ➡️ 타입 지정, 널 허용 여부, 체크, 기본값 등의 제약이 있음.

 *  엔티티 무결성 레코드끼리 중복값을 가지지 않도록 하여 유일한 식별자를 관리.
     예를 들어 주민등록번호가 같은 두 명이 존재하지 않아야 함. 기본키와 유니크 제약이 있음.

 *  참조 무결성 테이블간의 관계를 구성하는 키가 항상 유효하도록 관리하며 외래키 제약으로 관리.

 

 

INSERT INTO tCity VALUES ('대구', '꽤 넓음', '200만명', 'n', '대한민국'); // 실행시 에러가 남
 

  📍 인구나 면적은 수치형이어서 123 같은 숫자만 가능하며 문자열은 저장할 수 없음. 타입이 맞더라도 지정한 길이를 초과 x

  📍 타입은 물리적인 형태만 지정할 뿐 논리적인 값까지 점검하지는 못 함  ex. 음수 or 지나치게 큰 수

        ➡️ 논리적인 값까지 저장할 수 있는 장치가 필요. DBMS는 주로 제약을 사용

 

👩🏻‍💻  '제약 Constraint'은 조건을 위반하는 데이터를 방지하여 완결성을 보장하는 규칙

  📍 제약이 없으면 무결성이 쉽게 깨짐

  📍 편집창에서 필드의 입력값 형태를 미리 지정해두는 것이 바로 제약이며 이 규칙에 맞는 데이터만 입력받음

        ➡️ 쿼리문에서는 NULL, NOT NULL, PRIMARY KEY 같은 속성으로 제약을 지정

 

 


 

2.  NULL 허용

 

👩🏻‍💻 NULL은 아무것도 입력되지 있지 않은 것이며 알 수 없거나 결정되지 않은 특수한 상태를 의미

👩🏻‍💻 필드의 NULL 허용 속성은 NULL 상태가 존재하는지를 지정

 

  ⚡️ 반드시 입력해야 하는 필수 필드는 NULL을 허용 x, 없어도 괜찮은 필드는 NULL을 허용 o

         ➡️ 필수 정보 : 아이디, 이름, 비밀번호, 이메일

        ➡️ 필수 정도 아닌 것 : 홈페이지, 주소, 전화번호

  ⚡️ Nullable (Null 허용), Not Nullable(Null 허용 x)

 

// tCity 테이블의 생성 스크립트
CREATE TABLE tCity (
 name CHAR(10) PRIMARY KEY,
 area INT NULL ,
 popu INT NULL ,
 metro CHAR(1) NOT NULL,
 region CHAR(6) NOT NULL
);
 

  📌  name, metro, region 필드는 PRIMARY KEY 또는 NOT NULL 속성이 있어 NULL을 허용하지 않음을 지정

  📌  반면 area와 pupu 필드는 NULL 속성으로 지정되어 있어 생략 가능

 

 

👩🏻‍💻  INSERT 명령으로 레코드를 삽입할 때 NOT NULL로 지정한 필드는 반드시 입력해여 함

       ➡️ 필수 정보 중 하나라도 빼 먹으면 정상적인 정보가 아니라고 판단하여 레코드 삽입을 거부

// 다음 두 쿼리문은 정상 실행.
INSERT INTO tCity (name, popu, metro, region) VALUES ('울산', 114, 'y', '경상');
INSERT INTO tCity (name, metro, region) VALUES ('삼척', 'n', '강원');
 

 

  📌 울산은 면적을 모르는 상태여서 area 필드는 빼고 입력 ( 생략한 area는 NULL이 됨 )

  📌 삼척은 인구, 면적을 다 생략

 

 


 

// 다음 두 쿼리문은 에러가 남.
INSERT INTO tCity (area, popu, metro, region) VALUES (456, 123, 'n', '충청');
INSERT INTO tCity (name, area, popu) VALUES ('의정부', 456,123);
 

📌 충청도에 있는 어느 도시인데 이름은 없음. 필수 값이 누락되어 에러

📌 의정부는 있지만 소속과 광역시 여부가 없어 역시 무효한 정보이면 DBMS는 이런 무효한 레코드의 삽입을 거부

 


 

⚡️ NULL 허용 여부를 생략해 버리면 어떻게 될까?

 

CREATE TABLE tNullable (
 name CHAR(10) NOT NULL,
 age INT
);
 

  📌  name은 필수 필드임이 분명하나 age는 정수형이라는 것만 밝혔을 뿐 NULL 허용 여부에 대한 지정이 없음

  📌  NULL 허용 여부를 생략하면 DBMS의 디폴트 허용 여부를 따른다.

 

INSERT INTO tNullable (name, age) values ('흥부', 36);
INSERT INTO tNullable (name) values ('놀부');
INSERT INTO tNullable (age) values (44);
 

📌 모든 필드값을 다 입력한 흥부는 에러 없이 입력이 된다.

📌 나이를 생략한 놀부는 DBMS의 설정에 따라 입력될 수도 있고 아닐 수도 있다.

      ➡️ 대부분의 DBMS는 NULL 허용이 디폴트여서 이상 없이 삽입될 확률이 높음

📌 이름을 생략하고 나이 44세만 입력하면 에러

 

 


 

⚡️ NULL 허용 속성은 디폴트는 DBMS마다 다르며 데이터베이스나 연결 수준에서 변경할 수도 있다.

⚡️ 그러나 설정에 영향을 받는 명령은 일관성이 없어 위험함

⚡️ 속성을 생략하지 말고 필드 선언문 끝에 항상 NULL, NOT NULL을 분명히 명시하는 것이 바람직하다.

 

 


 

3.  기본값

 

👩🏻‍💻 NULL 허용 속성은 데이터베이스의 성능을 저해하는 주범

       ➡️ 항상 NULL 상태를 감안하여 필드값이 존재하는지 점검해야 하고 보통의 값과는 다루는 방식이 달라 느릴 수 밖에 없다.

👩🏻‍💻 NULL 허용 대신 기본값 DEFAULT을 사용하는 것이 성능상 유리.

👩🏻‍💻 기본값은 필드값을 지정하지 않을 때 자동으로 입력할 값

      ➡️ 보통 무난한 값을 지정하는데 수치형은 0이 적당하고 문자열을 비워 두거나 'N/A'등을 많이 사용

 

 

⚡️ 도시중 광역시는 몇 개 되지 않으며 대부분 지역에 소속

⚡️ 이럴 때 metro 필드 속성에 DEFAULT 키워드와 함께 디폴트 값을 'n'으로 지정

⚡️ DEFAULT 키워드는 NULL 허용 속성보다 앞에 와야 함 (MariaDB는 순서를 강제하지 않지만 오라클은 순서를 바꾸면 에러 처리)

CREATE TABLE tCityDefault (
 name CHAR(10) PRIMARY KEY,
 area INT NULL ,
 popu INT NULL ,
 metro CHAR(1) DEFAULT 'n' NOT NULL, // 값을 괄호로 감싸 DEFAULT('n')이라고 적어도 됨
 region CHAR(6) NOT NULL
);
 
 

  📌 새로운 레코드를 삽입할 때 metro 필드를 지정하지 않으면 자동으로 'n'을 적용

  📌 기본값은 입력하지 않을 때만 적용하는 것, 값을 직접 지정하면 기본값을 무시하고 지정한 값을 적용

 

INSERT INTO tCityDefault (name, area, popu, region) 
  VALUES ('진주', 712, 34, '경상');
INSERT INTO tCityDefault (name, area, popu, metro, region)
  VALUES ('인천', 1063, 295, 'y', '경기');
 

 

📌 진주시는 면적, 인구, 지역만 지정하고 광역시 여부는 생략.

      ➡️ 필드 목록에 metro가 아예 없는데 이 경우 디폴트가 적용되어 광역시가 아닌 것으로 삽입

📌 인천시는 모든 필드의 값을 다 제공하여 광역시로 등록

 


 

⚡️ 기본값 설정도 편집 가능해서 테이블 생성시와 달라질 수 있다.

 

INSERT INTO tCityDefault VALUES ('강릉', 1111, 22, '강원'); -- 에러
INSERT INTO tCityDefault VALUES ('강릉', 1111, 22, DEFAULT, '강원'); -- 정상 실행
 

  📌 필드 목록을 생략하면 값 목록이 완전해야 함

  📌 metro에 기본값이 있더라도 값 목록에 이 자리는 비우면 안된다.

  📌 값 목록을 완전히 적되 기본값을 적용할 필드값에 DEFAULT라고 적음. 기본값으로 변경할 때도 DEFAULT 키워드를 사용.

 

// 다음 명령을 인천의 metro 필드를 기본값인 'n'으로 변경.
 UPDATE tCityDefault SET metro = DEFAULT WHERE name = '인천'
 

 

 

 

⚡️ 기본값의 유무와 NULL 허용 여부는 완전히 별개의 속성임을 주의

⚡️ 기본값이 지정되어 있더라도 NULL을 직접 입력할 수 있고, UPDATE 명령으로 NULL로 바꿀 수도 있음.

⚡️ 기본값은 생략시 적용할 값일 뿐이지 NULL 허용 여부까지 통제하는 것은 아님.

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

 


 

1. 필드 비교 [ Where 절 ]

👾 WHERE 절은 읽을 레코드의 조건을 지정. ( * 필드 목록은 읽을 열을 지정하는데 비해 WHERE 절은 읽을 행을 지정 )

      ➡️  주로 필드와 특정값을 비교하는 조건문 형태로 작성한다.

👾 SELECT 명령은 조건에 맞는 레코드를 검색하는 것이 주 기능이어서 대개의 경우 WHERE 절과 함께 사용.

👾 WHERE 절은 DELETE, UPDATE 등의 명령과 함께 삭제 및 변경할 레코드를 선택할 때도 사용.

 

SELECT * FROM tCity WHERE area > 1000;
SELECT name, area  FROM tCity  WHERE  area > 1000;

 

 

📌 면적이 1000제곱킬로미터 보다 큰 도시만 검색.

📌 필드 목록에 * 대신 원하는 필드만 적으면 조건에 맞는 레코드의 지정한 필드만 표시.

📌 조건문은 필드와 상수, 변수 등을 표현식이되고 비교 대상끼리 타입이 호환되어야 함.

      ➡️  정수형을 문자열과 비교한다거나 실수형을 날짜와 비교해서는 안됨.


 

💡 조건문에 사용하는 비교 연산자

연산자
설명
A = B
같다.
WHERE name = '서울'
A > B
A가 더 크다.
WHERE area > 50
A < B
A가 더 작다.
WHERE popu < 100
A >= B
A가 B보다 크거나 같다.
WHERE popu >= 100
A <= B
A가 B보다 작거나 같다.
WHERE area <= 50
A <> B, A != B
A와 B는 다르다. 또는 같지 않다.
WHERE region <> '경기'

 


 

 

👾 숫자는 상수를 그냥 쓰지만 문자열과 날짜 상수는 항상 작은 따옴표로 감싸야 함.

👾 따옴표없이 서울이라고 하면 필드명을 의미.

 

SELECT * FROM `tCity` WHERE `name` = '서울' ( o )
SELECT * FROM tCity WHERE name = '서울' ( o )
SELECT * FROM tCity WHERE name = 서울 ( x )
SELECT * FROM tCity WHERE name = "서울" ( x )

 

 

 

👾 필드의 영문자를 비교할 때는 대소문자 주의. SQL문 자체는 대소문자를 가리지 않아 키워드나 테이블명, 필드명을 아무렇게나 적어도 상관이 없지만, 필드안에 저장된 값은 대소문자를 구분. 필드값의 대소문자 구분 여부는 DBMS에 따라, 설정에따라 다름. 어떤 DBMS를 사용하건 따옴표 내의 문자열 상수는 가급적 대소문자를 정확히적는 것이 바람직.

SELECT * FROM tCity WHERE metro = 'y' ;
SELECT * FROM tCity WHERE metro = 'Y' ;

 

실행 결과

 


 

 

2. NULL 비교

 

👾 NULL은 값이 입력되어 있지 않은 특수한 상태를 표현. 값을 알 수 없거나 아직 결정할 수 없다는 뜻이며 0이나 빈 문자열과는 다름.

👾 필드를 선언할 때 NULL 가능성을 미리 지정한다. 선언문 뒤에 NULL이 있으면 이 필드는 값을 입력하지 않아도 된다는 뜻

 

CREATE TABLE tCity (
name CHAR(10) PRIMARY KEY,
area INT NULL,
popu INT NULL,
metro CHAR(1) NOT NULL,
region CHAR(6) NOT NULL
);

 

 

  📌 인구와 면적이 NULL 가능하다고 되어 있음. 정보가 아직 조사되지 않았거나 모르는 상태일 때 이 필드를 NULL로 남겨 둠.

  📌 반면 광역시 여부나 지역은 NOT NULL로 선언 되어 있어 값이 없으면 레코드를 삽입할 수 없음.

 

 

SELECT * FROM tStaff WHERE score = NULL;       ( x )
SELECT * FROM tStaff WHERE score IS NULL;      ( o )
SELECT * FROM tStaff WHERE score IS NOT NULL;  ( o )

 

  📌 NULL 값을 검색할려고 조건절에서 = NULL 로 작성.

  📌 NULL은 값이 아니라 상태이기 때문에 = 연산자로 비교할 수 없음.

       ➡️ IS NULL 연산자를 따로 제공.

       ➡️ NULL이 아니라는 조건은 IS NOT NULL로 표기.

 

 

 


 

 

3. 논리 연산자

 

👾 두 개 이상의 조건을 동시에 검색할 때는 AND, OR 논리 연산자를 사용

👾 AND는 두 조건이 모두 참인 레코드를 검색하며 OR는 두 조건 중 하나라도 참인 레코드를 검사.

 

SELECT * FROM tCity WHERE popu >=100 AND area >= 700;

 

 

 

📌 인구 100만명 이상, 면적 700제곱킬로미터 이상인 도시를 검색하여

두 조건을 만족하는 부산만 출력.

 

 

SELECT * FROM tCity WHERE popu >=100 OR area >= 700;

 

 

 

 

📌 AND를 OR로 변경하면 두 조건중 하나라도 참인 레코드 검색.

 

 

 

 

 

 

 

👾 세 개 이상의 조건문을 지정할 때도 마찬가지로 WHERE 절을 작성하되 조건의 우선순위에 주의

👾 AND의 우선 순위가 OR 보다 높다. 애매할 경우에는 괄호로 우선 순위를 지정하는 것이 좋음.

 

SELECT * FROM tCity WHERE region = '경기' AND popu >= 50 OR area >= 500;
SELECT * FROM tCity WHERE area >= 500 OR region = '경기' AND popu >= 50 ;

 

 

 

 

📌 경기권 도시중 인구 50만이상이거나 또는 경기권이 아니고 인구가 50만보다 적더라도 면적이 500 이상인 도시를 검색

 

 

 

SELECT * FROM tCity WHERE region = '경기' AND (popu >= 50 OR area >= 500);

 

 

📌 인구가 50만이 넘거나 면적이 500이상인 경기도 도시를 검색.

 

 


👾 NOT 연산자는 표현식의 진위 여부를 반대로 바꿈. 즉 뒤의 표현식이 참이면 거짓으로 바꾸고 거짓이면 참으로 바꾸어 반대 조건을 취함.

SELECT * FROM tCity WHERE region != '경기';
SELECT * FROM tCity WHERE NOT (region = '경기');

 

 

 

 

📌 경기도 소속이 아닌 도시의 정보를 조사. 복합 조건의 반대를 취할때는 NOT이 편리.

 

 

 

 

 

SELECT * FROM tCity WHERE region = '전라' OR metro = 'y'; // 전라도에 있거나 광역시인 도시
SELECT * FROM tCity WHERE region != '전라' AND metro != 'y'; // 위의 조건의 반대
SELECT * FROM tCity WHERE NOT(region = '전라' OR metro ='y');

 

 

📌 A AND B의 부정은 !A OR !B 이며 이를 모르간의 법칙

 


 

 

4. LIKE

 

👾 '=' 비교 연산자를 완전히 일치하는 조건식을 표현하는데 비해 LIKE 연산자는 패턴으로 '부분 문자열'을 검색.

ex. 성이 김씨인 사람, 주소가 강남구인 사람들을 검색할 때 편리

 

⚡️ LIKE 문의 패턴에 사용하는 와일드 카드 ⚡️

 
문자
설명
%
복수 개의 문자와 대응. %자리에는 임의 개수의 임의 문자가 올 수 있음
_
하나의 문자와 대응 _자리에는 하나의 임의 문자가 올수 있음
[]
[]안에 포함된 문자 리스트 중 하나의 문자와 대응
[^]
[^]안에 포함된 문자 리스트에 포함되지 않은 하나의 문자와 대응

👾 임의 개수의 임의 문자와 대응하는 % 와일드 카드를 주로 사용한다.

 

SELECT * FROM tCity WHERE name LIKE '%천%';

 

 

 

📌  이름에 "천"자가 들어가는 도시를 검색

 

 

 

SELECT * FROM tCity WHERE name LIKE '천%';

 

 

📌  "천"으로 시작하는 도시를 검색

 

 

 

SELECT * FROM tCity WHERE name LIKE '%천';

 

 
📌  "천"으로 끝나는 도시를 검색.

📌  '%천'의 경우 처리하는 DBMS나 타입별로 차이가 있음.

📌  공백 제거를 위해 아래와 같이 작성하기도 함.

      SELECT * FROM tCity WHERE TRIM(name) LIKE '%천' ;

 

 


 

 

5. BETWEEN

 

👾 BETWEEN A AND B 문은 "BETWEEN 최소값 AND 최대값" 형식으로 두 값 사이의 범위를 제한

👾 BETWEEN ~ AND 문은 작은 값, 큰 값 순이 상식적이어서 실수할 위험이 낮으며 구문 전체가 하나의 조건이어서 가독성이 높음.

👾 이상, 이하의 범위만 가능하며 미만, 초과는 지정할 수 없는 활용성의 한계가 있음.

👾 문자열이나 날짜에도 사용 가능. ( * 문자열은 사전순으로 비교 )

 

SELECT * FROM tCity WHERE popu BETWEEN 50 AND 100;
SELECT * FROM tCity WHERE popu >= 50 AND popu <= 100;

 

 

 

📌 인구가 50 ~ 100만 사이의 도시를 구함.

📌 "~ 보다 크고 ~ 보다 작다" 조건의 조합이어서 AND 논리 연산자로 대체 가능

 

 

 

SELECT * FROM tStaff WHERE name BETWEEN '가' AND '사';

 

 
SELECT * FROM tStaff WHERE joindate BETWEEN '20150101' AND '20180101';

 

 

 


 

 

 

6. IN

 

👾 BETWEEN 연산자는 연속된 범위만 검색할 수 있으며 불연속적이고 임의적인 값 여러 개를 조사하기 어려움.

👾 이에 비해 IN 연산자는 불연속적인 값 여러 개의 목록을 제공하여 이 목록과 일치하는 레코드를 검색.

👾 IN 연산자 뒤의 괄호 안에 콤마로 구분된 값 목록을 나열하여 이 중 하나에 해당하는지 점검.

👾 값 개수에는 제한이 없다.

 

SELECT * FROM tCity WHERE region IN ('경상','전라');
SELECT * FROM tCity WHERE region = '경상' OR region = '전라';

 

 

📌  region 필드가 '경상' 또는 '전라'인 모든 도시를 조사.

📌  IN 연산자는 여러 값 중 하나라도 해당하는지 점검하므로 각각의 비교문을 OR 논리 연산자로 연결하여 표현가능.

 

 

 

 

👾  값 리스트가 많은 경우 일일히 OR 연산자로 조건을 연결하는 것보다 IN 연산자로 값만 나열하는 것이 짧고 읽기 쉬움.

      추후 값 리스트를 편집하기도 편해 관리상의 이점이 있음.

👾  IN 연산자의 반대 조건은 NOT IN

 

SELECT * FROM tCity WHERE region NOT IN ('경상','전라');

 

 

 

📌  경상도와 전라도에 있지 않은 도시 목록을 조사

 

 

 

 

 

 

👾  부분 문자열 여러 개 중 하나에 해당하는지 찾으려면 LIKE와 IN 연산자를 같이 써야 하지만 SQL 표준에서 지원하지 않음.

      ➡️  즉 LIKE와 IN 연산자는 같이 사용할 수 없음. 이런 검색을 하고 싶으면 각각의 LIKE 조건을 OR 연산자로 연결

 

SELECT * FROM tStaff WHERE name LIKE IN ('이%', '안%'); ( x )
SELECT * FROM tStaff WHERE name LIKE '이%' OR name LIKE '안%';

 

 

 

 

📌  직원 목록에서 이씨와 안씨를 찾음

 

 

 

 

 

 

 

 

[ 내용 출처 ; IT 학원 강의 ]

+ Recent posts