contents
chapter 02.실전용 SQL 미리 맛보기
2-2.데이터베이스 시작부터 끝까지
5)데이터 활용하기
2-3.데이터베이스 개체
chapter 03.SQL 기본 문법
3-1.SELECT~FROM~WHERE
3-2.SELECT 문
----------------------------
chapter 02.실전용 SQL 미리 맛보기
2-2.데이터베이스 시작부터 끝까지
5)데이터 활용하기
-데이터까지 입력하여 데이터베이스 구축을 완료함. 데이터베이스를 활용하는 방법을 살펴봄. SQL에서는 데이터베이스를 활용하기 위해 주로 SELECT 문을 사용하며, SELECT 문을 활용하는 내용이 가장 많은 비중을 차지함. 직접 SQL을 입력해서 데이터를 조회해봄
-먼저 회원 테이블의 모든 행을 조회하기 위해 다음 SQL 입력함. SELECT의 기본 형식은 SELECT 열_이름 FROM 테이블_이름 [WHERE 조건]이고, *는 모든 열을 의미함. 따라서 '회원 테이블의 모든 열을 보여줘'라는 의미임
| SELECT * FROM member; |
실행 결과
![]() |
| select * from product; |
실행 결과
![]() |
◎SQL의 대소문자
-SQL은 대소문자를 구분하지 않음. SQL의 제일 뒤에는 세미콜론(;)이 꼭 있어야 됨. 가끔 없어도 되는 경우도 있지만 그걸 모두 기억하는 것보다 있어야 한다고 생각하는 게 더 편함
-여러 개의 열 이름을 콤마(,)로 분리하면 필요한 열만 추출됨
| select member_id, member_name, member_addr from member; |
실행 결과
![]() |
| select member_addr from member; |
실행 결과
![]() |
-앞의 SQL을 지우지 말고 다음 줄에 이어서 다음과 같이 입력한 후 실행함. 데이터를 조회하는 SQL 형식은 SELECT 열_이름 FROM 테이블_이름[WHERE 조건] 임. WHERE 다음에 특정 조건을 입력하여 회원 이름(member_name)이 '아이유'인 회원만 출력되도록 한 것임. 그런데 [Result Grid] 창의 아래쪽 탭을 살펴보면 2개의 SQL이 모두 실행된 것을 확인할 수 있음
| select member_name, member_addr from member; -- 컬럼을 선택 행을 선택 select * from member where member_id='iyou'; |
실행 결과
![]() |
*2개의 SQL 결과가 모두 나온 것은 SQL을 실행할 때 쿼리 창에 있는 모든 SQL을 수행하기 때문임. 지금은 SELECT만 있고 두 줄뿐이므로 큰 문제가 없지만, 향후에 여러 개의 SQL을 사용할 때 주의해야 함. 이런 경우를 방지하기 위해 1개의 SQL만 남기고 모두 지우는 방법도 있지만, 더 편리한 방법은 필요한 부분만 마우스로 드래그해서 선택한 후에 실행하는 것임
◎SQL 예약어와 자동 완성
-쿼리 창에서 SQL을 입력하면 예약어는 자동으로 파란색으로 표시됨. 예제로 사용한 SELECT, FROM은 이미 SQL에서 약속된 예약어이므로 파란색으로 표시됨
-또한 MySQL 워크벤치는 IntelliSense 또는 AutoComplete 기능을 제공하는데, 이는 글자의 일부만 입력해도 그와 관련된 글자들이 미리 제시되는 것을 말함
-자동 완성 기능을 사용하려면 MySQL 워크벤치의 [Edit]-[Rreference] 메뉴에서 [SQL Editor]-[Query Editor]의 'Automatically Start Code Completion'이 체크되어 있어야 함. 기본은 체크되어 있음
2-3.데이터베이스 개체(Object, instance(객체 생성한 것))
-테이블은 데이터베이스의 핵심 개체임. 하지만 데이터베이스에서는 테이블 외에 인덱스, 뷰, 스토어드 프로시저, 트리거, 함수, 커서 등의 개체도 필요함
-인덱스는 데이터를 조회할 때 결과가 나오는 속도를 획기적으로 빠르게 해주고, 뷰는 테이블의 일부를 제한적으로 표현할 때 주로 사용함. 스토어드 프로시저는 SQL에서 프로그래밍이 가능하도록 해주고, 트리거는 잘못된 데이터가 들어가는 것을 미연에 방지하는 기능을 함
-모든 데이터베이스 개체는 독립적으로 존재하는 것이 아니라 테이블과 상호 연관이 있음
*인덱스와 트리거는 테이블 안에 포함됨
![]() |
1)인덱스
-데이터를 조회(SELECT)할 때 테이블에 데이터가 적다면 결과가 금방 나오지만 데이터가 많아질수록 결과가 나오는 시간이 많이 소요됨. 인덱스는 이런 경우 결과가 나오는 시간을 대폭 줄여줌
*SELECT 할 때 좀 더 빨리 검색해서 결과를 반환할 수 있게 도와주는 개체(검색엔진)
◎인덱스 개념 이해하기
-인덱스(index)란 책의 제일 뒤에 수록되는 '찾아보기'와 비슷한 개념임. 책의 내용 중에서 특정 단어를 찾고자 할 때, 책의 처음부터 마지막까지 한 페이지씩 전부 찾아보는 것은 상당히 시간이 오래 걸림. 그래서 찾아보기를 통해 해당 단어를 찾고 바로 옆에 적혀 있는 페이지로 이동하는 효율적인 방법을 사용하는 것임
-다음 SQL을 실행하면 인덱스가 생성됨. 인덱스는 열에 지정함. SQL의 마지막에 On member(member)name)의 의미는 member 테이블의 member_name 열 인덱스를 지정하라는 의미임. 결과는 특별히 눈에 보이지 않음
| create index test on member(member_name); SHOW INDEX FROM member; -- 기존 인덱스 확인 DROP INDEX test ON member; -- 인덱스 삭제 |
실행 결과
-[Execution Plan] 탭을 보면 Non-Unique Key Lookup이라고 나옴. Key Lookup은 인덱스를 통해 결과를 찾았다고 기억하면 됨. 이런 방법을 인덱스 검색(Index Scan)이라고 부름
-인덱스에서 한 가지 더 기억해야 할 점은 인덱스 생성 여부에 따라 결과가 달라지는 것은 아니라는 것임. 즉 책의 내용을 찾을 때 찾아보기가 있으면 시간을 단축하는 효과는 있지만, 책의 찾아보기가 없어도 책의 첫 페이지부터 찾아야 하기 때문에 시간이 오래 걸릴 뿐 어차피 동일하게 찾을 수는 있음
2)뷰
-뷰는 테이블과 상당히 동일한 성격의 데이터베이스 개체임. 뷰를 활용하면 보안도 강화하고, SQL 문도 간단하게 사용할 수 있음
◎뷰 개념 이해하기
-뷰(view)를 한마디로 정의하면 '가상의 테이블'이라고 할 수 있음. 일반 사용자의 입장에서는 테이블과 뷰를 구분할 수 없음. 즉, 일반 사용자는 테이블과 동일하게 뷰를 취급하면 됨. 다만 뷰는 실제 데이터를 가지고 있지 않으며, 진짜 테이블에 링크(link)된 개념이라고 생각하면 됨
-뷰는 윈도우즈 운영 체제의 '바로 가기 아이콘'과 비슷한 개념임. 윈도우즈에서 바탕 화면의 바로 가기 아이콘을 더블 클릭해서 실행하지만, 실제로 실행되는 파일은 다른 폴더에 있음. 예를 들어, 바탕 화면에 있는 크롬 브라우저의 바로 가기 아이콘은 C:\Program Files\Google/Chrome\Application 폴더의 chrome.exe와 연결되어 있음
-뷰도 비슷한 개념으로 실체는 없으며 테이블과 연결되어 있는 것 뿐임. 사용자가 뷰를 테이블처럼 생각해서 접근하면 알아서 테이블에 연결해줌. 뷰의 실체는 바로 SELECT문임
-테이블을 사용하지 않고 굳이 뷰를 사용하는 이유는 보안에 도움이 되며, 긴 SQL 문을 간략하게 만들 수 있기 때문임
3)스토어드 프로시저
-스토어드 프로시저를 통해 SQL 안에서도 일반 프로그래밍 언어처럼 코딩을 할 수 있음. 비록 일반 프로그래밍보다는 좀 불편하지만, 프로그래밍 로직을 작성할 수 있어서 때론 유용하게 사용됨
◎스토어드 프로시저 개념 이해하기
-스토어드 프로시저(stored procedure)란 MySQL에서 제공하는 프로그래밍 기능으로, 여러 개의 SQL 문을 하나로 묶어서 편리하게 사용할 수 있음. SQL을 묶는 개념 외에 C, 자바, 파이썬과 같은 프로그래밍 언어에서 사용되는 연산식, 조건문, 반복문 등을 사용할 수도 있음
-스토어드 프로시저를 통해서 MySQL에서도 기본적인 형태의 일반 프로그래밍 로직을 코딩할 수 있음
-두 SQL을 하나의 스토어드 프로시저로 만듬. 첫 행과 마지막 행에 구분 문자라는 의미의 DELIMITER// ~ DERIMITER; 문이 나옴. 일단 이것은 스토어드 프로시저를 묶어주는 약속임. 그리고 BIGIN과 END 사이에 SQL 문을 넣으면 됨
| DELIMITER $$ create procedure myProc() -- 스토어드 프로시저 이름 지정 begin select * from member where member_name = '나훈아'; select * from product where product_name = '삼각김밥'; end $$ DELIMITER ; call myProc(); |
*//: $$ 대신 사용가능
-이제부터 두 줄의 SQL 문을 실행할 필요 없이 앞에서 만든 스토어드 프로시저를 호출하기 위해서 CALL 문을 실행하면 됨. 두 SQL을 실행한 것과 동일함
실행 결과
![]() |
◎CREATE 문과 DROP문
-테이블, 인데스, 뷰, 스토어드 프로시저 등의 데이터베이스 개체를 만들기 위해서는 CREATE 개체_종류 개체_이름 ~~ 형식을 사용함. 반대로 데이터베이스 개체를 삭제하기 위해서는 DROP 개체_종류 개체_이름 형식을 사용함. 예로, 실습에서 생성한 스토어드 프로시저를 삭제하려면 DROP PROCEDURE myproc를 사용함
-MySQL 워크벤치에서 생성, 삭제하려면 먼저 [SCHEMAS] 패널의 빈 곳에서 마우스 오른쪽 버튼을 클릭하고 [Refresh All]을 선택해서 새로 고침함. 그리고 생성, 삭제할 데이터베이스 개체에서 마우스 오른쪽 버튼을 클릭하고 생성하려면 [Create 데이터베이스_개체]를, 삭제하려면 [Drop 데이터베이스_개체]를 선택함
◎관련 중요 용어
| 한글 용어 | 영문 용어 | 설명 |
| 데이터베이스 개체 | Database Object | 테이블, 뷰, 인덱스, 스토어드 프로시저 등 데이터베이스 안에 저장되는 개체 |
| 실행 계획 | Execution Plan | SQL 을 실행할 때, 인덱스 사용 여부를 확인할 수 있는 워크벤치의 화면 |
| 전체 테이블 검색 | Full Table Scan | 테이블의 모든 데이터를 훑어서 원하는 데이터를 찾아내는 것을 말함. 책 전체를 찾아보는 것과 비슷함 |
| 인덱스 검색 | Index Scan | 인덱스를 통해서 데이터를 찾는 것을 말함. 책 뒤의 찾아보기를 사용한 것과 비슷함 |
| 구분 문자 | DELIMITER | 스토어드 프로시저를 묶어주는 예약어 |
| 호출 | CALL | 스토어드 프로시저를 호출하는 예약어 |
| 개체 생성문 | CREATE | 데이터베이스 개체를 생성할 때 사용하는 예약어 |
| 개체 삭제문 | DROP | 데이터베이스 개체를 삭제할 때 사용하는 예약어 |
chapter 03.SQL 기본 문법
3-1.SELECT~FROM~WHERE
-SELECT 문은 구축이 완료된 테이블에서 데이터를 추출하는 기능을 함. 그러므로 SELECT를 아무리 많이 사용해도 기존의 데이터가 변경되지는 않음
-SELECT의 가장 기본 형식은 SELECT ~ FROM ~ WHERE임. SELECT 바로 다음에는 열 이름이, FROM 다음에는 테이블 이름이 나옴. WHERE 다음에는 조건식이 나오는데, 조건식을 다양하게 표현함으로써 데이터베이스에서 원하는 데이터를 뽑아낼 수 있음
-SELECT 문은 데이터베이스의 테이블을 조회한 후 결과를 보여줌
1)실습용 데이터베이스 구축
(1)데이터베이스 만들기
| DROP DATABASE IF EXISTS market_db; -- 만약 market_db가 존재하면 우선 삭제한다. CREATE DATABASE market_db; |
-DROP DATABASE는 market_db를 삭제하는 문장임. IF EXISTS는 존재할 때만 실행하는 부가명령임
(2)회원 테이블(member)/ 구매 테이블(buy) 만들기
| USE market_db; CREATE TABLE member -- 회원 테이블 ( mem_id CHAR(8) NOT NULL PRIMARY KEY, -- 사용자 아이디(PK) mem_name VARCHAR(10) NOT NULL, -- 이름 mem_number INT NOT NULL, -- 인원수 addr CHAR(2) NOT NULL, -- 지역(경기,서울,경남 식으로 2글자만입력) phone1 CHAR(3), -- 연락처의 국번(02, 031, 055 등) phone2 CHAR(8), -- 연락처의 나머지 전화번호(하이픈제외) height SMALLINT, -- 평균 키 debut_date DATE -- 데뷔 일자 ); CREATE TABLE buy -- 구매 테이블 ( num INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -- 순번(PK) mem_id CHAR(8) NOT NULL, -- 아이디(FK) prod_name CHAR(6) NOT NULL, -- 제품이름 group_name CHAR(4) , -- 분류 price INT NOT NULL, -- 가격 amount SMALLINT NOT NULL, -- 수량 FOREIGN KEY (mem_id) REFERENCES member(mem_id) ); |
*SQL에서 하이픈(-) 2개가 연속되면, 그 이후는 주석(remark)으로 취급함. 즉, 코드의 설명으로 처리되어 없는 것과 마친가지임. 주의할 점은 하이픈 2개 이후에 한 칸을 띄고 설명을 작성해야 함
-USE 문은 데이터베이스를 선택하는 문장임 ex)import와 유사
-CHAR: 고정 정적 크기, 속도↑, 공간多/ VARCHAR: 동적 크기, 속도↓, 데이터 공간少
-AUTO_INCREATE는 자동으로 숫자를 입력해준다는 의미임. 즉, 순번은 직접 입력할 필요 없이 1, 2, 3, ...과 같은 방식으로 자동으로 증가함
-FOREIGN KEY는 외래키로 기본키를 참조함
(3)데이터 입력하기
| INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19'); INSERT INTO member VALUES('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08'); INSERT INTO member VALUES('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15'); INSERT INTO member VALUES('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21'); INSERT INTO member VALUES('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02'); INSERT INTO member VALUES('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12'); INSERT INTO member VALUES('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01'); INSERT INTO member VALUES('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10'); INSERT INTO member VALUES('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25'); INSERT INTO member VALUES('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19'); INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2); INSERT INTO buy VALUES(NULL, 'BLK', '맥북프로', '디지털', 1000, 1); INSERT INTO buy VALUES(NULL, 'APN', '아이폰', '디지털', 200, 1); INSERT INTO buy VALUES(NULL, 'MMU', '아이폰', '디지털', 200, 5); INSERT INTO buy VALUES(NULL, 'BLK', '청바지', '패션', 50, 3); INSERT INTO buy VALUES(NULL, 'MMU', '에어팟', '디지털', 80, 10); INSERT INTO buy VALUES(NULL, 'GRL', '혼공SQL', '서적', 15, 5); INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 2); INSERT INTO buy VALUES(NULL, 'APN', '청바지', '패션', 50, 1); INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 1); INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 1); INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 4); |
-INSERT문은 데이터를 입력하는 것으로 테이블에 값을 입력함. CHAR, VARCHAR, DATE 형은 작은따옴표로 값을 묶어줌. INT형은 작은 따옴표 없이 그냥 넣어주면 됨
-구매 테이블(buy)의 첫 번째 열인 순번(num)은 자동으로 입력되므로 그 자리에서 NULL이라고 써주면 됨. 그러면 알아서 1, 2, 3, ... 으로 증가하면서 입력됨. 여기서는 처음이므로 1이 입력됨
(4)데이터 조회하기
| SELECT * FROM member; SELECT * FROM buy; |
-입력된 내용을 확인하기 위해 SELECT로 조회함
2)기본 조회하기: SELECT ~ FROM
(1)USE 문
-SELECT 문을 실행하려면 먼저 사용할 데이터베이스를 지정해야 함. 현재 사용하는 데이터베이스를 지정 또는 변경하는 혁식은 다음과 같음
| USE 데이터베이스_이름; |
-USE 문은 '지금부터 이 DB를 사용하겠으니 모든 쿼리는 이 DB에서 실행하라'는 의미임
*MySQL 워크벤치를 재시작하거나 쿼리 창을 새로 열면 다시 USE를 실행해야 함. 현재 선택된 데이터베이스에 테이블이 없으면 오류가 발생함
(2)SELECT 문의 기본 형식
-SELECT 문은 처음에는 사용하기 간단하지만, 사실 상당히 복잡한 구조를 갖음
| SELECT 열_이름 FROM 테이블_이름 WHERE 조건식 GROUP BY 열_이름 HAVING 조건식 ORDER BY 열_이름 LIMIT 숫자 |
(3)SELECT와 FROM
| USE market_db; SELECT * FROM member; (1) (2) (3) (4) |
(1)테이블에서 데이터를 가져올 때 사용하는 예약어임. 가장 많이 사용함
(2)일반적으로 '모든 것'을 의미함. 그런데 *가 사용된 위치가 열 이름이 나올 곳이므로 모든 열을 말함
(3)FROM 다음에 테이블 이름이 나옴. 테이블에서 내용을 가져온다는 의미임
(4)조회할 테이블 이름임
-SELECT 문에서 테이블 이름은 원칙적으로 데이터베이스_이름.테이블_이름 형식을 사용해야 하지만 대부분 테이블_이름만 사용함
◎[Output] 패널의 의미
-[Output] 패널에서 제일 앞의 아이콘과 [Message] 정도는 확인하는 것이 좋음. [Output] 패널의 의미는 다음과 같음
·초록색 체크 표시: SQL이 정상적으로 실행되었다는 의미임
·빨간색 X 표시: SQL에 오류가 발생했다는 의미임
·#: 실행한 SQL의 순번임. 실행한 SQL이 여러 개라면 1, 2, 3, ... 순서로 증가함
·Time: SQL을 실행한 시각이 표시됨
·ActionL 실행된 SQL이 표시됨
·Message: SELECT 문이 조회된 행의 개수가 나옴. 만약 오류 발생 시에는 오류 번호 및 오류 메시지가 표시됨
·Duration/ Fetch: Duration은 SQL 문이 실행되는 데 걸린 시간(초), Fetch는 데이터베이스에서 가져온 시간(초)임
-여러 개의 열을 가져오고 싶으면 콤마(,)로 구분하면 됨. 열 이름의 순서는 원래 테이블을 만들 때 순서에 맞출 필요 없음. 보고 싶은 순서대로 나열하면 됨
| select mem_id "그룹아이디", mem_name 이름, addr '주소' from member; |
실행 결과
![]() |
*열 이름에 별칭(alias)을 지정할 수 있음. 열 이름 다음에 지정하고 싶은 별칭을 입력하면 됨. 별칭에 공백이 있으면 큰따옴표(")로 묶어줌 ex) SELECT debut_date "데뷔 일자" FROM member;
3)특정한 조건만 조회하기: SELECT ~ FROM ~ WHERE
-SELECT ~ FROM은 대부분 WHERE와 함께 사용함. WHERE는 필요한 것들만 골라서 결과를 보는 효과를 갖음
◎WHERE 없이 조회하기
-WHERE가 없이 SELECT ~ FROM 만으로 테이블을 조회하면 테이블의 모든 행이 출력됨. 데이터 건수가 적은 경우에는 별 문제가 없지만, 실제 회원이 수백만 명 이상이 되는 인터넷 쇼핑몰에서 회원 테이블을 검색하면 결과가 엄청나게 많이 나옴. 출력된 수백만 건 이상의 결과에서 필요한 데이터를 눈으로 찾아내는 것은 상당히 어려울 뿐만 아니라, 이렇게 많은 데이터를 출력하면 아무리 고성능의 컴퓨터라도 부담이 될 수 밖에 없음. 그래서 작은 데이터를 조회할 때를 제외한 SELECT 문은 WHERE 절과 함께 사용함
-실무에서 SELECT 문을 사용할 때는 대부분 WHERE 절을 함께 사용함
◎기본적인 WHERE 절
-WHERE 절은 조회하는 결과에 특정한 조건을 추가해서 원하는 데이터만 보고 싶을 때 사용함
| SELECT 열_이름 FROM 테이블_이름 WHERE 조건식; |
ex) if(true/false)
또는
| SELECT 열_이름 FROM 테이블_이름 WHERE 조건식; |
*이 형식에서 세미콜론(;)이 나오기 전까지는 한 줄로 쓰든, 여러 줄로 쓰든 동일함. SQL이 길거나 복잡한 경우에는 여러 줄로 나눠 쓰는 것이 좀 더 읽기 편함
-열_이름 = 값은 열의 값에 해당하는 결과만 출력해줌
| select * from member where mem_id= "APN"; |
실행 결과
![]() |
| select * from member where mem_name= '블랙핑크'; |
실행 결과
![]() |
| select * from member where mem_number = 4; |
실행 결과
![]() |
| -- READ Date select "hi"; select abcd "hi" 6 -- 이름 문자열 숫자 |
◎관계 연산자, 논리 연산자의 사용
-숫자로 표현된 데이터는 범위를 지정할 수 있음. 예를 들어 평균 키(height)가 162 이하인 회원을 검색하려면 다음과 같이 관계 연산자 <= (작거나 같다)를 사용해서 조회할 수 있음
| select mem_id, mem_name from member where height <= 162; |
*관계연산자는 >, <, >=, <=, = 등이 있음
실행 결과
![]() |
-2가지 이상의 조건을 만족하도록 할 수도 있음. 평균 키(height)가 165 이상이면서 인원(mem_number)도 6명 초과인 회원은 다음과 같이 논리 연산자 AND를 이용해서 조회할 수 있음
| select mem_name, height, mem_number from member where height >= 165 and mem_number > 6; |
실행 결과
![]() |
-평균 키(height)가 165 이상이거나 인원(mem_number)이 6명 초과인 회원은 다음과 같이 논리 연산자 OR를 이용해서 조회할 수 있음. AND가 두 조건이 모두 만족해야 하는 것이라면, OR는 두 조건 중 하나만 만족해도 됨
| select mem_name, height, mem_number from member where height >= 165 or mem_number >6; |
실행 결과
![]() |
◎BETWEEN ~ AND
-AND를 사용해서 평균 키(height)가 163 ~ 165인 회원을 조회함
| select mem_name, height from member where height >= 163 and height <= 165; |
실행 결과
![]() |
-그런데 범위에 있는 값을 구하는 경우에는 BETWEEN ~ AND를 사용해도 됨. 다음 SQL은 바로 앞에서 살펴본 AND를 사용한 SQL과 동일함. 숫자의 범위를 조건식에서 사용할 때는 BETWEEN ~ AND가 편리함
| select mem_name, height from member where height between 163 and 165; |
실행 결과
![]() |
◎IN()
-평균 키(height)와 같이 숫자로 구성된 데이터는 크다/작다의 범위를 지정할 수 있으므로 BETWEEN ~ AND를 사용할 수 있지만, 주소(addr)와 같은 데이터는 문자로 표현되기 떄문에 어느 범위에 들어 있다고 표현할 수 없음. 만약, 경기/전남/경남 중 한 곳에 사는 회원을 검색하려면 다음과 같이 OR로 일일이 써줘야 함
| select mem_name, addr from member where addr = '경기' or addr = '전남' or addr='경남'; |
실행 결과
![]() |
-IN()을 사용하면 코드를 훨씬 간결하게 작성할 수 있음. 다음은 바로 앞의 SQL 문과 동일한 결과를 냄. 조건식에서 여러 문자 중 하나에 포함되는지 비교할 때는 IN()이 간결함
| select mem_name, addr from member where addr in('경기', '전남', '경남'); |
실행 결과
![]() |
◎LIKE
-문자열의 일부 글자를 검색하려면 LIKE를 사용함. 이 조건은 제일 앞 글자가 '우'이고 그 뒤는 무엇이든(%) 허용한다는 의미임
| select * from member where mem_name like '우%'; |
실행 결과
![]() |
*우%: '우'로 시작하는 것
%우%: '우'가 포함된 것
%우: '우'로 끝나는 것
-한 글자와 매치하기 위해서 언더바(_)를 사용함. 다음 SQL은 이름(mem_name)의 앞 두 글자는 상관없고 뒤는 '핑크'인 회원을 검색함
| select * from member where mem_name like '__핑크'; -- 언더바 2개 |
![]() |
*언더바(_): 글자수 제한
◎서브 쿼리
-SELECT 안에는 또 다른 SELECT가 들어갈 수 있음. 이것을 서브 쿼리(subquery) 또는 하위 쿼리라고 부름
| SELECT mem_name, height FROM member WHERE height > (SELECT height FROM member WHERE mem_name = '에이핑크'); |
-세미콜론(;)이 하나이므로 이 SQL은 하나의 문장임. SQL 안에 또 SQL이 들어간 모양임. 즉, 괄호 안의 SELECT 결과가 164이므로 이 자리에 164를 직접 써준 것과 동일한 효과를 얻음. 서브 쿼리의 장점은 2개의 SQL을 하나로 만듦으로써 하나의 SQL만 관리하면 되므로 더 간단해진다는 것임. 실무에서도 종종 사용됨
◎관련 중요 용어
| 용어 | 영문 용어 | 설명 |
| 주석 | remark | 하이픈(-) 2개와 설명으로 구성 |
| VARCHAR | 문자형으로 CHAR와 거의 비슷함 | |
| AUTO_INCREMENT | 자동으로 숫자를 입력시켜줌. 테이블을 생성할 때 지정함 | |
| * | 모든 열을 지정할 때 사용하는 기호 | |
| 별칭 | alias | SELECT 문에서 실제 열 이름 대신에 출력되도록 설정하는 문자 |
| % | 문자열에서 여러 문자에 대응하는 기호 | |
| _ | 문자열에서 한 문자에 대응하는 기호 |
3-2.SELECT 문
-SELECT 문에서는 결과의 정렬을 위한 ORDER BY, 결과의 개수를 제한하는 LIMIT, 중복된 데이터를 제거하는 DISTINCT 등을 사용할 수 있음
-그리고 GROUP BY 절은 지정한 열의 데이터들을 같은 데이터끼리는 묶어서 결과를 추출함. 주로 그룹으로 묶는 경우는 합계, 평균, 개수 등을 처리할 때 사용하므로 집계 함수와 함께 사용됨. GROUP BY 절에서도 HAVING 절을 통해 조건식을 추가할 수 있음. HAVING 절은 WHERE 절과 비슷해 보이지만, GROUP BY 절과 함께 사용되는 것이 차이점임
1)ORDER BY 절
| SELECT 열_이름 FROM 테이블_이름 WHERE 조건식 GROUP BY 열_이름 HAVING 조건식 ORDER BY 열_이름 LIMIT 숫자 |
-ORDER BY 절은 결과의 값이나 개수에 대해서는 영향을 미치지 않지만, 결과가 출력되는 순서를 조절함. 오름차순 또는 내림차순으로 정렬해서 결과를 보여줌
| select mem_id, mem_name, debut_date from member order by debut_date; |
실행 결과
![]() |
-기본값은 ASC인데 Ascending의 약자로 오름차순을 의미하고, DESC는 Descending의 약자로 내림차순을 의미함. ASC 또는 DESC를 생략하면 기본적으로 ASC라고 인식함
| select mem_od, mem_name, debut_date from member order by debut_date desc; |
실행 결과
![]() |
-ORDER BY 절과 WHERE 절은 함께 사용할 수 있음. 그런데 SQL 구문의 순서가 틀렸기 때문에 오류가 발생함
| select mem_id, mem_name, debut_date from member order by height desc where height >= 164; -- > 오류 발생 |
실행 결과
![]() |
*MySQL 워크벤티의 쿼리 창에서 SQL 입력 시 문제가 발생하면 행 번호 뒤에 빨간색 X 모양이, 해당 부분에 빨간색 줄이 표시됨
-ORDER BY 절은 WHERE 절 다음에 나와야 함. SELECT 문에 나오는 절은 생략 가능하지만, 사용해야 한다면 순서를 지켜야 함
| select mem_id, mem_name, debut_date, height from member where height >= 164 order by height desc; |
실행 결과
![]() |
-정렬 기준은 1개 열이 아니라 여러 개 열로 지정할 수 있음. 우선 첫 번째 지정 열로 정렬한 후에 동일한 경우에는 다음 지정 열로 정렬할 수 있음. 즉, 평균 키가 큰 순서대로 정렬하되, 평균 키가 같으면 데뷔 일자가 빠른 순서로 정렬함
*없으면 PK 기준으로 정렬
| select mem_id, mem_name, debut_date, height from member where height >= 164 order by height desc, debut_date asc; |
실행 결과
![]() |
◎출력 개수를 제한: LIMIT
-LIMIT는 출력하는 개수를 제한함. 예를 들어, 회원 테이블(membeR)을 조회하는데 전체 중 앞에서 3건만 조회할 수 있음
| select * from member limit 3; |
실행 결과
![]() |
-결과에는 문제가 없지만, 이렇게 아무런 기분 없이 앞에서 3건만 뽑는 경우는 별로 없음. 먼저 정렬한 후 앞에서 몇 건을 추출하는 것이 대부분임. 예를 들어, 데뷔 일자(debut_date)가 빠른 회원 3건만 추출하려면 다음과 같이 ORDER BY와 함께 사용할 수 있음
-LIMIT 형식은 LIMIT 시작, 개수임. 지금과 같이 LIMIT 3만 쓰면 LIMIT 0, 3과 동일함. 즉, 0번째부터 3건이라는 의미임
-LIMIT는 개수를 제한해서 보여주며, 주로 ORDER BY와 함께 사용함
| select mem_name, debut_date from member order by debut_date limit 3; |
실행 결과
![]() |
-필요하다면 중간부터 출력도 가능함. 다음과 같이 평균 키(height)가 큰 순으로 정렬하되, 3번째부터 2건만 조회할 수 있음
| select mem_name, height from member order by height desc limit 3, 2; |
실행 결과
![]() |
*LIMIT 시작, 개수는 LIMIT 개수 OFFSET 시작이라고 쓰는 것과 동일함. 또한 LIMIT는 첫 데이터를 0번으로 설정하고 시작함
◎중복된 결과를 제거: DISTINCT
-DISTINCT는 조회는 결과에서 중복된 데이터를 1개만 남김. 여기서는 회원들의 지역(addr)을 출력해봄
-다음 SQL의 결과를 보면 회원이 사는 지역(addr)은 경기, 경남, 서울, 전남, 경북 등 5군데인 것을 확인할 수 있음. 데이터가 적은데도 중복된 것을 눈으로 골라내기 힘듬
| select addr from member; |
실행 결과
![]() |
-ORDER BY를 통해 같은 지역(addr)끼릴 몰려 있어서 아까보다 세기는 쉽지만 이 역시 데이터 건수가 수만 개라면 현실적으로 종류를 세는 것은 너무 어려움
| select addr from member order by addr; |
실행 결과
![]() |
-이를 간단하게 하는 것이 DISTINCT 문임. 열 이름 앞에 DISTINCT를 써주기만 하면 중복된 데이터를 1개만 남기고 제거함
| select distinct addr from member; |
실행 결과
![]() |
-DISTINCT를 열 이름 앞에 붙이면, 중복된 값은 1개만 출력됨
'벡엔드 웹프로그래밍 > 데이터베이스 SQL' 카테고리의 다른 글
| 데이터베이스 SQL 72일차 (25/2/27) (2) | 2025.02.27 |
|---|































