SQL
SQL은 무엇일까 게시판 프로젝트를 진행해 보면서 어떻게 데이터베이스와 통신을 할지 궁금해졌다. 그래서 spring을 사용하고 있는 시점인 지금 순수 JDBC를 사용해서 쿼리를 만들어서 날리려고 했지만 생각보다 쉽지 않았다. 생각해 보면 이제 막 스프링에 대해서 공부를 시작하고 있었고 데이터베이스 관련 지식에 대해서는 전무했기 때문에 쿼리를 짜보는 것도 쉽지 않았다. 또 안드로이드 Firbase 클론 채팅 프로젝트를 해보면서 NoSQL을 먼저 경험해 봤기 때문에 관계형 데이터베이스의 중요성 그리고 왜 사용해야 하는지와 같은 필수적인 기초 개념들을 제대로 알지 못하고 사용했었기 때문에 백엔드 공부를 시작하고자 하는 지금 SQL에 대해서 기본문법과 왜 사용해야 하는지 그리고 어디에 쓰일 수 있는지를 명확히 아는 게 중요한 것 같다. 따라서 오늘의 포스팅 주제는 데이터베이스에 대해서 잘 알고 있는 사람들을 대상으로 작성되는 게시물이 아니다.
SQL을 학습하기 시작한 이유
SQL은 무엇일까 항상 프로젝트를 하면서 귀에 피가 나도록 들었던 것 같다. 디비랑 연결은 했나? 어떤 DB로 연결했는가? 쿼리는 어떻게 짰는가? 도대체 SQL이 무엇인데 매 프로젝트에서 항상 SQL이란 단어가 나오고 디비라는 내용이 들려왔을까.. 조금 더 근본적인 문제를 해결하고자 해왔던 프로젝트들에 대해서 살펴보면 클론 채팅 같은 경우도 파이어베이스를 사용해서 채팅 내역을 저장하지만 그게 큰 의미를 부여할 만큼의 내용은 아니었던 것 같았다. 왜냐하면 그때는 데이터베이스와의 통신이 중요한 상황이 아니었고 어떻게 디자인을 할 수 있고 안드로이드는 어떻게 개발이 되는지에 대해서 학습의 중점을 맞췄기 때문이다. 결국 해당 프로젝트에서도 데이터베이스라는 것을 정확히 알지 못했고, 데이터베이스를 사용해야 되는 이유에 대해서도 정확히 알지 못했기 때문에 흐지부지 넘어갔던 것 같다. 두 번째는 학교에 다시 복학하면서 여름방학 동안 개발한 풀스택 프로젝트였다. 음.. 말이 풀스택이지만 사실 정적인 웹 애플리케이션이라고 봐도 무방한 프로그램이지만 해당 프로그램에 대해서 정말 열심히 개발했고, 몰랐던 부분에 대해서 많이 알았다고 자부할 수 있을 정도의 프로젝트라고 생각한다. 또한 해당 프로젝트를 기점으로 백엔드 공부를 시작한 계기가 되었으므로 시간을 낭비한 프로젝트라고 생각 또한 하지 않는다. 다만 해당 프로젝트에서도 데이터베이스와의 연동은 생각하지 않았고 딱히 필요하지도 않았다. 웹에 있는 localstorage 만으로도 충분히 개발이 가능했었기 때문이었다. 그렇다 보니 해당 프로젝트에서도 데이터베이스와의 연동은 생각조차 하지 않게 되었다. 그러다 해당 프로젝트를 완성하고 위에 기술했었던 것처럼 백엔드 공부를 시작하려고 기본적인 게시판 프로젝트에 대해서 공부해 가던 중. 게시판에 있는 정보들을 저장을 해야 될 필요성이 생겨났다. 그래서 데이터베이스에 대해서 지식은 없는 상태로 무작정 인터넷을 뒤져가며 쿼리문을 찾아서 작성해 보았지만 이게 무슨 의미가 있겠는가. 나한테 도움이 되지도 않을뿐더러 제대로 알고 사용하는 게 아니기 때문에 동적인 상황에서는 내가 제대로 알지 못하는 지식은 여전히 배제된다. 따라서 데이터베이스 지식이 없기 때문에 유연한 상황에 대처하지 못한다는 의미와 같다. 그래서 나는 SQL을 학습하려고 기초적인 구문에 대해서 다시 한번 정리한 뒤 마지막에 프로그래머스에서 제공해 주는 SQL문제 한 문제를 분석해서 풀어보며 포스팅을 마치려고 한다.
SQL이 그래서 무엇일까
SQL은 Structured Query Language 구조화된 쿼리 언어정도로 해석해 볼 수 있을 것 같다. 구조화된 쿼리 언어가 무엇일까. 위키 피디아에선 아래와 같이 정의하고 있다.
Structured Query Language is a domain-specific language used in programming and designed for managing data held in a relational database management system
https://en.wikipedia.org/wiki/SQL
해석해 보면 결국 관계형 데이터베이스 시스템에서 사용되는 언어라는 뜻이다. 흔히 데이터베이스는 저장소라고 많이 알고 있다. 저장소가 맞기 때문이다. 어떠한 데이터를 Persistence 영속성을 유지하기 위해서 단발성인 데이터가 아닌 영구적으로 저장하기 위해 사용하기 때문이다. 물론 의미상 영구적인 목적이지만 CRUD를 통해서도 당연히 삭제가 가능하다. 우선 관계형이라는 의미가 무엇일까를 생각해 볼 필요가 있다. 의미상 관계는 어떻게 연관이 되어 있을까? 정도로 생각해 볼 수 있을 것 같다. 따라서 데이터들의 관계가 어떻게 표현되어 있는지 그리고 그렇게 표현되어 있는 데이터를 관리하는 시스템이바로 관계형 데이터베이스 시스템인 셈이다. 이를 줄여 RDBMS라고 불린다. 이때 쿼리라는 개념을 처음 듣게 되었는데 쿼리라는 개념은 query 자체가 질문하다, 요청하다는 뜻을 가지고 있다. 프로그래밍에서는 이를 데이터베이스에 요청하다. 정도로 표현할 수 있다. 그렇기 때문에 쿼리라는 건 데이터베이스에 어떠한 정보를 요청해서 받아내는 것이라고 볼 수 있다. 그때 컴퓨터에 말로 요청할 수 없으니 query라는 명령어들의 집합으로 되어 있는 것을 사용하게 되고 그때 사용되게 되는 언어가 SQL인 것이다. 결국 SQL은 데이터베이스에게 데이터를 요청하기 위해 사용되는 언어이며 이러한 언어들의 기능들을 사용해 데이터베이스에게 정보를 요청하게 된다.
SQL이 꼭 필요할까?
당연하다면 당연하다고 말할 수 있는 부분 또한 존재하겠지만 나는 앞서 개인 프로젝트를 개발해 가면서 내가 흥미 있고 실현 가능한 아이디어를 개발하는 걸 좋아했다. 그때마다 데이터베이스에 굳이 저장할 필요가 없는 대표적인 프로젝트가 웹 풀스택 개발 프로젝트지만 완전히 사용하지 않았다는 건 아니고 로컬 스토리지를 사용했다. 다만 관계형 데이터베이스를 사용하지 않았다는 표현이 더 맞을 것 같다. 그래서 필요되는 시스템이 존재하고 그와 반면에 필요하지 않은 시스템 들도 존재한다. 하지만 일상생활 속에서 데이터베이스를 사용하지 않는 애플리케이션 혹은 프로그램들을 찾기가 더 어려울지도 모르겠다. 그만큼 데이터를 보관하는 것이 애플리케이션을 운영하거나 개발하는 데에 필수적인 요소로 작용하고 있기 때문이지 않을까 생각해 본다. 따라서 위 질문에 대해서는 생각하기 나름인 것 같다. 또한 꼭 관계형 데이터베이스를 사용해서만 데이터를 저장할 필요도 없을 것 같다고 생각도 했다. 데이터를 저장하는 방법은 다양하기 때문이다.
SQL 기본동작 원리
작성하다 보니 이런저런 생각을 더 정리하는데 소비한 것 같다. 해당 섹션에서는 본격적으로 SQL 기본 문법에 대해서 살펴보자.
SELECT * FROM BOOK
해당 문장을 어떻게 해석할 수 있을까? 직관적으로 영어 해석 하듯이 한다면 선택한다 *를 book으로부터 이 정도로 해석할 수 있지 않을까? 자연스럽지는 않지만 문장의 의미는 어느 정도 통한다고 느껴진다. 결국 BOOK이라는 데이터들의 집합인 테이블을 선택해서 * 에스터리스크 라고 하여 모든 데이터들을 추출할 때 사용한다. 따라서 BOOk이란 테이블에 있는 모든 데이터들을 가지고 오자.라는 뜻 정도로 볼 수 있다. 그럼 아래와 같은 내용은 어떤 내용을 포함하고 있을까?
SELECT * FROM student where 학년 < 4 AND 주소 LIKE '서울특별시%';
문장은 길어졌지만 추가된 내용은 where, AND, LIKE, %일 뿐이다. 우선 where 같은 경우는 조건절을 명시할 때 사용한다. 따라서 where뒤에 가 조건절이 되고 AND 전까지가 그 유효범위를 갖는다. 그럼 학년이 4학년 미만인 학생들 중에서 정도로 조건절을 해석할 수 있다. 그럼 AND를 살펴보자. 프로그래밍을 조금이라도 해본 사람이라면 AND는 A와 B 둘다 참일 때 즉 논리연산을 하기 위해 사용되는 것임을 알 수 있다. 따라서 where 학년 < 4 가 a가 되는 것이고 AND 뒤에가 b가 되는 것이다. 그렇다면 A와 B 둘 다 참이어야 참을 리턴한다고 볼 수 있다. 이제 마지막 문장인 B를 보자 LIKE '서울특별시%' 이는 주소라는 행(Column) 중에서 서울특별시를 포함하고 % 뒤에 있는 건 어떠한 값이 와도 상관없는 것들 정도로 해석해 볼 수 있다. %라는건 와일드카드 문자라고 하여 서울특별시로 시작하는 모든 문자열을 선택하라는 의미를 담고 있다. 따라서 서울특별시는 무조건 포함해야 되며 서울특별시 강남구, 서울특별시 종로구와 같은 뒤에는 어떠한 값이 오더라도 상관이 없다. 중요한 건 와일드카드 문자 앞에 있는 것은 무조건 포함을 해야 된다는 의미다. 그럼 이제 기본적으로 어떻게 SQL이 해석되는지 알 수 있게 되었으니 아래 쿼리를 살펴보자.
SELECT * FROM grade where 성적 IS NOT NULL;
위에 문장도 어렵지 않게 해석이 된다. 결국 성적이 null이 아닌 값을 가져오라는 얘기가 된다. 데이터베이스에서 null이라는 값은 데이터가 없는 것을 표현한다. 따라서 해당 성적이라는 행에 대해서 값이 없는 것만 가지고 오라는 얘기가 된다. 그럼 전체적으로 성적 = null 인 어떠한 행들의 집합만이 표현될 것이다. 그럼 이제 아래는 무엇일지 고민해 보자.
SELECT * FROM student where 학년 <= 4 ORDER BY 학년 DESC;
위 문장도 어렵지 않게 해석은 될 수 있으나 order by라는 새로운 명령어가 나왔다. 이는 sort() 함수와 똑같다고 생각하면 편하다. 왜냐하면 정렬하게 되는 기능을 지닌 명령어기 때문이다. 따라서 학년이 4학년 이하인 학생들을 표시해 주긴 하는데 그때 학년을 기준으로 내림차순으로 정렬을 하라는 말이다. 내림차순이라는 건 숫자가 큰 순서대로 차례로 정렬을 해달라는 의미기 때문에 1.. 2.. 3.. 4 이렇게 표현되던 게 4... 3.. 2.. 1 이렇게 표현이 된다는 얘기가 된다. 따라서 테이블의 가장 위에 학년은 4학년이 되고 아래로 갈수록 학년이 줄어들게 표현이 될 것이다.
CRUD
위에서는 SQL의 기본 문법들만을 사용해서 SQL의 동작방식을 이해해 보았다. 이제 데이터베이스 테이블을 생성하고, 읽고, 업데이트하고, 삭제하는 것까지에 대해서 알아보고자 한다. 왜 기본을 위에서 끝냈는지에 대한 이유는 어떤 구조로 돌아가는지에 대해서 알고 있다면 부속 명령어들은 검색을 통해 학습해 가며 알아가는 것이 더 효율적이라고 생각했기 때문에 SQL의 기본 동작방식을 위한 명령어들만 구성했다.
CREATE TABLE [테이블명] (
제품 INT PRIMARY KEY,
제품이름 VARCHAR NOT NULL,
가격 INT DEFAULT 0
);
위 쿼리문은 데이터베이스 테이블을 생성하는 데 사용한다. 그 아래는 제품, 제품이름, 가격 이러한 것들은 칼럼명을 지정해 준다. 해당 테이블에 칼럼명이 가지고 있는 데이터 타입과, 조건을 설정한다. 이때 조건이라고 한다면 PRIMARY KEY와 NOT NULL인데 조건은 기본적으로 여러 개가 있지만 필수적인 것만 좀 살펴본다면 PRIMARYKEY는 해당 칼럼을 기본키로 지정할 때 사용한다. 즉 칼럼의 기본이 되는 키로 설정하여 다른 테이블과 조인을 하거나 혹은 해당 칼럼에 대한 기준값이 필요로 될 때 사용할 수 있다. NOT NULL은 값이 없으면 안 된다는 뜻이 된다. NULL에 NOT이 붙었기 때문에 NULL이면 안된다가 된다. DEFAULT는 값이 입력되지 않는다면 기본값은 0으로 지정하겠다는 의미가 된다. 따라서 0에 해당하는 부분은 테이블을 설계할 때 지정할 수 있을 것이다. 그 외에도 여러 데이터 타입들이 존재하며 필요에 따라 적절히 사용하면 될 것 같다. 그럼 CRUD 중 C와 R은 알아보았다. R은 이미 SELECT 구문을 사용하면서 알아봤기 때문에 따로 작성은 하지 않는다.
INSERT INTO 제품(제품이름, 가격) VALUES('마우스', 10000);
UPDATE 제품 SET 제품이름 = '키보드', 가격='15000 where 제품 = 1;
DELETE FROM 제품 WHERE 제품 = 1;
DROP TABLE 제품;
나머지 것들을 적어 보았는데 생각보다 어렵지 않게 해석이 가능하다. INSERT는 말 그대로 특정 테이블에 제품이름이라는 테이블과 가격이라는 테이블에 마우스와 10000원만큼 데이터를 추가하기 위해서 사용한다. 이는 게시판을 개발하다 보면 어떤 특정 댓글이 추가되어야 하는 상황이 생기는데 그때 사용되는 구문이다. INSERT 데이터를 제품에 넣어주는 것이 바로 이와 같은 구문을 사용해서 진행된다. UPDATE는 말 그대로 데이터 값을 경신하는 용도가 된다. 제품이라는 테이블에 있는 칼럼들을 조건값들만큼 갱신하는 의미가 되는데 이때 특정 where 조건을 걸어 1번 데이터 값만을 바꾸겠다는 의미가 된다. DELETE 같은 경우 제품 테이블 안에 있는 제품 = 1번인 데이터 행을 삭제하겠다는 의미가 된다. 이를 사용할 때 where 조건절을 걸지 않아 모든 데이터가 다 삭제될 수 있으니 주의하며 사용해야 한다. DROP 은 테이블 자체를 삭제하는 게 되는데 DELETE와의 차이점은 쉽게 알아볼 수 있으며 테이블을 삭제하는 건 DROP, 테이블에 있는 행을 삭제하는 게 DELETE가 된다.
SQL을 연습해 보면서 한 문제를 풀고 마무리하자
https://school.programmers.co.kr/learn/courses/30/lessons/144853
코드
select BOOK_ID, DATE_FORMAT(PUBLISHED_DATE, '%Y-%m-%d') as 'PUBLISHED_DATE' from BOOK where year(PUBLISHED_DATE) = '2021' and Category = '인문';
설명
위에 문제는 Level.1문제다 기본 문법을 숙지하는 문제로 보면 새로운 걸 배워간다. 우선 DATE_FORMAT 은 DATE 타입의 값을 특정 FORMAT으로 변경하는 함수다. 따라서 PUBLISHED_DATE라는 필드가 가지고 있는 데이터 타입은 DATE이며 그때 년, 월, 일, 시간까지 나오는 데이터 포맷에서 시간 데이터는 날리고 년 월 일 데이터만 뽑아오게 된다. 반대로 년 월 일을 제외하고자 한다면 DATE_FORMAT(PUBLISHED_DATE, '% H:%i:%s') 이렇게 작성하게 되면 시간만 나오게 된다. 이후에 year()라는 함수는 특정 DATE 타입을 가지고 있는 필드에서 특정 년에 해당하는 데이터만 추출할 수 있다. 그렇기 때문에 PUBLISHED_DATE 필드에 있는 모든 데이터들의 year 정보만 가져와서 그때 2021년인 데이터가 AND 조건에 첫 번째가 되고 이후에는 Category 조건을 맞춘 데이터를 뽑아주게 된다. 이렇게 이번 포스트는 기본적인 SQL의 동작 구조 그리고 간단한 문제를 풀어보면서 어떻게 SQL을 다루어야 할지 감을 잡는 포스팅이 되었다.
'SQL' 카테고리의 다른 글
[프로그래머스] 없어진 기록 찾기 (Lv.3 - select 에 혹시 유실된 데이터를 보려고 하지 않았는지??) (0) | 2024.02.24 |
---|---|
[SQL] 자동차 대여 기록에서 장기/단기 대여 구분하기 [알고 있는 것을 다시 체크해보자] (0) | 2023.08.26 |
[SQL] 역순 정렬하기 [단순하게 order by를 사용하면 안되는이유] (0) | 2023.08.26 |