SQL 문
쉽게 말하면
SQL은 데이터베이스에게 말을 거는 문장이에요. 'SELECT 이름 FROM 학생 WHERE 학년=3'은 '학생 표에서 3학년의 이름을 골라 줘'라는 뜻이에요. Access 쿼리 디자인 보기에서 만든 쿼리도 속으로는 이런 SQL 문장으로 저장돼요.
시험용 정의
SQL(Structured Query Language)은 관계형 데이터베이스를 다루는 표준 언어다. 검색은 SELECT 필드 FROM 테이블 [WHERE 조건] [GROUP BY 필드] [HAVING 그룹 조건] [ORDER BY 필드 ASC|DESC] 순서로 쓴다. SELECT *는 모든 필드, DISTINCT는 중복 행 제거, AS는 필드·테이블 별명이다. WHERE는 레코드를 고르는 조건이고, GROUP BY로 같은 값끼리 묶은 뒤 그룹에 조건을 걸 때는 HAVING을 쓴다. ORDER BY는 기본이 오름차순(ASC)이고 내림차순은 DESC이며, 여러 필드를 쓰면 앞 필드가 같을 때 뒤 필드로 정렬한다. 집계 함수 COUNT·SUM·AVG·MAX·MIN 중 COUNT(*)는 모든 레코드 수, COUNT(필드)는 그 필드가 Null이 아닌 레코드 수다. 여러 테이블은 FROM A INNER JOIN B ON A.키 = B.키(일치하는 행만)나 LEFT·RIGHT JOIN으로 잇고, 조건 안에 다른 SELECT를 넣는 하위 쿼리(WHERE 필드 IN (SELECT ...))도 쓴다. 데이터 조작은 INSERT INTO 테이블(필드들) VALUES(값들)(한 테이블에 레코드 추가, 모든 필드면 필드 목록 생략 가능, SELECT 결과를 넣으면 여러 레코드도 가능), UPDATE 테이블 SET 필드=값 WHERE 조건, DELETE FROM 테이블 WHERE 조건이다. 구조는 CREATE TABLE(PRIMARY KEY·NOT NULL·FOREIGN KEY 제약 지정), ALTER TABLE, DROP TABLE로 다룬다.
비유로 이해하기
SELECT 문은 식당 주문서다. '무엇을(SELECT) 어느 메뉴판에서(FROM) 어떤 조건으로(WHERE) 묶어서(GROUP BY) 묶은 것 중 이런 것만(HAVING) 어떤 순서로(ORDER BY)' 차례로 적는다.
자세히
SELECT 문 순서
SELECT 부서, AVG(급여) AS 평균급여 FROM 사원 WHERE 입사연도 >= 2020 ← 묶기 전에 레코드 고르기 GROUP BY 부서 ← 부서별로 묶기 HAVING AVG(급여) >= 3000000 ← 묶은 뒤 그룹 고르기 ORDER BY 평균급여 DESC; ← 큰 것부터
WHERE 다음에 ORDER BY가 온다. ORDER BY 뒤에 WHERE를 쓰면 오류다.
COUNT와 Null
아래 [회원] 테이블에서 빈칸은 Null이다.
이름 전화 가윤 010-1 나래 (빈칸) 다온 010-3
- SELECT COUNT(*) FROM 회원 → 3
- SELECT COUNT(전화) FROM 회원 → 2 (Null 제외)
- SELECT COUNT(*) FROM 회원 WHERE 전화 Is Null → 1
데이터 조작 문
| 문 | 형태 | 뜻 |
|---|---|---|
| INSERT | INSERT INTO 학생(학번, 이름) VALUES(101, '가윤') | 한 테이블에 레코드 추가 |
| UPDATE | UPDATE 학생 SET 주소='부산' WHERE 학번=101 | 101번 학생의 주소를 부산으로 |
| DELETE | DELETE FROM 학생 WHERE 학년=4 | 4학년 레코드 삭제 |
| CREATE | CREATE TABLE 계좌(번호 TEXT PRIMARY KEY, 고객ID TEXT NOT NULL, ...) | 기본 키는 중복·Null 불가 |
헷갈리기 쉬운 것
- UPDATE는 SET, INSERT는 INTO·VALUES
- INSERT 하나로 여러 테이블에 동시에 넣을 수는 없다
- 외래 키 필드(예: 계좌의 고객ID)는 같은 값이 여러 번 나올 수 있다 (일대다의 '다' 쪽)
- 참조 무결성이 있으면 INSERT도 부모 테이블에 있는 값만 외래 키로 넣을 수 있다
- DateDiff("yyyy", 시작일, Date())는 두 날짜 사이의 햇수
시험에 이렇게 나와요
- ORDER BY 기본값은 ASC, 여러 필드면 앞에서부터 (WHERE 뒤에 ORDER BY)
- COUNT(*)는 Null 포함 전체, COUNT(필드)는 Null 제외
- GROUP BY로 묶은 뒤 조건은 HAVING (WHERE 아님)
- UPDATE ~ SET ~ WHERE, INSERT INTO ~ VALUES, DISTINCT 중복 제거, AS 별명
- INSERT 하나로 여러 테이블에 동시 추가 불가
- CREATE TABLE의 PRIMARY KEY는 중복 불가, 외래 키 필드는 중복 가능
- INNER JOIN → 조인 필드가 일치하는 레코드만
확인 문제
Q1. ORDER BY 절에서 정렬 방식을 쓰지 않으면 어떻게 정렬될까?
- 입력 순서
- 정렬하지 않는다
- 오름차순(ASC)
- 내림차순(DESC)
정답 보기
3번 오름차순(ASC)
ORDER BY의 기본값은 오름차순 ASC다. 큰 값부터 보려면 DESC를 붙인다.
Q2. [상품] 테이블에서 재고가 10 이하인 상품을 가격이 비싼 순으로, 같은 가격이면 이름 순으로 보이는 SQL은?
- SELECT * FROM 상품 WHERE 재고<=10 ORDER BY 가격 DESC, 이름 ASC
- SELECT * FROM 상품 WHERE 재고<=10 ORDER BY 가격, 이름 DESC
- SELECT * FROM 상품 WHERE 재고<=10 GROUP BY 가격 DESC, 이름
- SELECT * FROM 상품 ORDER BY 가격 DESC, 이름 ASC WHERE 재고<=10
정답 보기
1번 SELECT * FROM 상품 WHERE 재고<=10 ORDER BY 가격 DESC, 이름 ASC
WHERE가 ORDER BY보다 앞에 오고, 비싼 순은 DESC다.
Q3. [직원] 테이블의 '부서'로 묶어 직원 수가 5명 이상인 부서만 보이려면 어떤 절이 필요할까?
- DISTINCT COUNT(*) >= 5
- ORDER BY COUNT(*) >= 5
- WHERE COUNT(*) >= 5
- HAVING COUNT(*) >= 5
정답 보기
4번 HAVING COUNT(*) >= 5
GROUP BY로 묶은 그룹에 거는 조건은 HAVING이다.
Q4. 회원 4명 중 1명의 '이메일'이 Null이다. SELECT COUNT(이메일) FROM 회원의 결과는?
- 0
- 1
- 3
- 4
정답 보기
3번 3
COUNT(필드)는 그 필드가 Null인 레코드를 세지 않는다.
Q5. [도서] 테이블에서 도서번호가 7인 도서의 가격을 15000으로 바꾸는 SQL은?
- UPDATE 도서 SET 가격=15000 WHERE 도서번호=7
- UPDATE 도서 WHERE 도서번호=7 SET 가격=15000
- INSERT INTO 도서 SET 가격=15000 WHERE 도서번호=7
- SELECT 도서 SET 가격=15000 WHERE 도서번호=7
정답 보기
1번 UPDATE 도서 SET 가격=15000 WHERE 도서번호=7
UPDATE 테이블 SET 필드=값 WHERE 조건 순서다.
헷갈리기 쉬운 O·X
SELECT DISTINCT는 결과에서 중복된 행을 없앤다.
정답 보기
O 같은 값을 가진 행을 하나만 남긴다.
INSERT 문 하나로 여러 테이블에 같은 레코드를 동시에 추가할 수 있다.
정답 보기
X INSERT INTO는 테이블 하나를 대상으로 한다.