DDLDMLUpdate from selectInsert from selectTCL커밋/롤백과는 상관없이 트랜잭션 적용 처리가 일어나는 상황WHERE절연산자의 종류CHAR vs VARCHAR2ROWNUM함수단일행 함수데이터 형변환의 방식단일행 CASE 표현의 종류NULL 관련함수GROUP BY, HAVING 절집계함수GROUP BY HAVING 절CASE WHEN 문 사용집계 함수와 NULLORDER BY 절SELECT 문의 실행 순서
DDL
- DB 를 구성하고 있는 다양한 객체(사용자, 테이블, 인덱스, 뷰, 트리거, 프로시저, 사용자 정의 함수 등)를 정의/변경/제거하는 데 사용함
테이블 생성 시 주의사항
- 테이블명은 단수형 사용할 것을 권고
- 테이블명과 컬럼명은 반드시 문자로 시작
- 테이블명에 사용하는 문자는 A-Z, a-z, 0-9, _, $ , # 문자만 허용함
제약조건
- 기본키 : UNIQUE + NOT NULL 제약조건 만족해야함. 기본키 생성 시 DBMS는 유일 인덱스를 자동으로 생성함
- 고유키 : UNIQUE 하지만 NULL 입력이 가능
- NOT NULL
- CHECK : 입력할 수 있는 값의 종류 혹은 범위를 제한
- 외래키 : 참조 무결성 제약조건이라고도 함(다른 테이블에 값이 있어야만 외래키로 INSERT가 가능함). 다른 테이블의 기본키를 외래키로 지정하는 경우 생성
- 디폴트 값(=기본값)
ALTER TABLE : 칼럼 및 제약조건을 추가/수정/제거하는 데 이용함
- 테이블 제거 (DROP TABLE …)
- 데이터 제거 (TRUNCATE TABLE …) : Truncate를 쓰면 Rollback으로 복구가 불가능함
CREATE TABLE < 이름> as SELECT * FROM ..
으로 테이블을 만들 때 복사되는것
- 테이블에 존재하는 칼럼명, 칼럼의 데이터 형, 칼럼 자체 제약 조건, 데이터
복사 되지 않는 것
- 기본키 제약 조건, 인덱스
DML
- 테이블의 데이터를 입력/수정/삭제/조회하는 역할
- 입력/수정/삭제는 SQL 실행 후 영구적으로 저장(COMMIT)하거나 수행 취소(ROLLBACK)할 수 있음
- SELECT 시 Alias 사용 가능
- Alias 시 컬럼이름 ‘’ 붙일 필요 없이 그냥 한글 써도 됨
- 테이블 명에 alias를 붙일때는 as 없이 그냥 뒤에 사용할 테이블 이름 쓰면됨
SELECT tp.POPLTN_SE_CD AS 성별구분코드 , tp.AGRDE_SE_CD AS 연령대구분코드 , SUM(tp.POPLTN_CNT) FROM TB_POPLTN tp GROUP BY tp.POPLTN_SE_CD, tp.AGRDE_SE_CD;
합성 연산자
사용. 여러 개의 컬럼을 한 컬럼으로 조회하고 싶을 때, || 를 이용해서 이어붙일 수 있음
Update from select
UPDATE [테이블A] SET [테이블A].필드 = [테이블B].필드 FROM [테이블A],[테이블B] WHERE [테이블A].id = [테이블B].id 출처: https://shakddoo.tistory.com/entry/Mysql-Select결과를-Update-문에-반영하기 [겨울팥죽 여름빙수:티스토리]
update 문의 set 에 해당하는 값을 상수값이 아닌 select 를 통해 동적으로도 업데이트가 가능함
update `user`, (select c._corporation_id, total.user_id from company c join ( select user_id, company_id from broker union select user_id, company_id from driver union select user_id, company_id from caller) as total on c.company_id = total.company_id where c._corporation_id is not null) B set user.membership_corporation_id = B._corporation_id where user.user_id = B.user_id
Insert from select
insert into membership_corporation ( membership_corporation_id , business_type, business_email, business_number, address_base, address_detail, address_zip_code, representative_name, representative_mobile, corporation_name, join_date_time, created_date_time, contact_name, bank_name, account_name, account_number ) SELECT `_corporation_id` , _business_type, `_email`, business_reg_num, address, address_detail, zip_code, representative , '', name , reg_dt , NOW(), contact_name , `_bank_name` , `_account_name` , `_account_number` from company c where c.`_corporation_id` is not null and c.business_reg_num not in (select business_number from membership_corporation);
TCL
- DML 문의 입력, 수정, 삭제를 실행하면 DB에 곧바로 적용되지 않고 커밋 명령을 실행해야만 DB에 최종 적용됨. 데이터를 변경한 후 커밋하지 않으면 ROLLBACK 으로 데이터의 변경을 취소할 수 있음
데이터 입력/수정/삭제 후 커밋 혹은 롤백 전 데이터 상태
- 최종 적용된 상태가 아니고 메모리에만 적용된 상태이므로 변경 이전 상태로 복구가 가능
- 입력/수정/삭제를 실행한 사용자는 SELECT 문으로 입력/수정/삭제 결과를 확인할 수 있다
- 입력/수정/삭제를 실행한 사용자 외 다른 사용자는(작업자가 해당 내용을 커밋하지 않는 이상) SELECT 문으로 입력/수정/삭제 결과를 확인할 수 없다
- 변경된 행은 락이 설정되므로 다른 사용자가 변경할 수 없다.
데이터 입력/수정/삭제 후 커밋 실행 후 상황
- 데이터의 입력/수정/삭제 내역이 DB에 완전히 반영
- 이전 데이터는 영원히 잃어버리게 됨
- 변경 사용자 및 변경 사용자가 아닌 다른 모든 사용자는 SELECT 문으로 입력/수정/삭제 결과를 볼 수 있다.
- 관련된 행에 대한 락이 풀리고, 모든 사용자들이 행을 조작할 수 있게 됨
SAVEPOINT
: 하나의 트랜잭션에서 여러 개의 입력/수정/삭제가 발생할 수 있는데 커밋과 롤백으로 여러 개의 변경된 내용을 취소하거나 적용할 수 있음. SAVEPOINT를 활용하면 해당 지점(SAVEPOINT를 선언한)까지의 데이터 변경만 유지하고 그 이후의 데이터 변경은 취소할 수 있음
커밋/롤백과는 상관없이 트랜잭션 적용 처리가 일어나는 상황
- 오라클 DBMS 기준으로 CREATE, ALTER, DROP, RENAME, TRUNCATE TABLE 등 DDL 문장을 실행하면 그 실행 전과 실행 후 시점에 자동으로 커밋이 됨
- DML 문 실행 후 커밋하지 않고 DDL 문을 실행하면 DDL 문 실행 전에 DML 문의 변경 사항이 자동으로 커밋됨
- 또한 DB 에 대한 접속을 종료하면 자동으로 이전 DML의 변경사항이 커밋이 됨
WHERE절
연산자의 종류
- 비교 연산자 : =, >,
>=
, <,<=
SQL 연산자
- BETWEEN A AND B
- IN (리스트)
- LIKE ‘비교문자열’ : LIKE 연산자 사용 시 % 라는 와일드카드를 이용할 수 있음
- %(퍼센트) : 0개 이상의 어떤 문자를 의미
- _(언더바) : 1개의 단일 문자를 의미
- IS NULL : NULL 인 행을 조회하고 싶을때 쓰는 연산자. == NULL 로는 조회가 불가능함
- IS NOT NULL : NULL이 아닌 행을 조회하고 싶을때 쓰는 연산자.
!=, <>, ^=
의 연산자로는 조회 불가능
논리 연산자
AND, OR, NOT
부정 비교 연산자
!=
<>
^=
- NOT 칼럼명 = : ~ 칼럼의 값이 ~와 같지 않다.
- NOT 칼럼명 > : ~ 칼럼의 값이 ~ 보다 크지 않다.
- NOT 칼럼명 < : ~ 칼럼의 값이 ~ 보다 작지 않다.
부정 SQL 연산자
- NOT BETWEEN A AND B
- NOT IN (LIST)
- IS NOT NULL
CHAR vs VARCHAR2
- CHAR는 고정 길이 문자열이고 VARCHAR2는 가변 길이 문자열임.
- CHAR(5)일 때, ‘SQLD’만 저장하면 뒤에 공백 붙어서 저장됨
- CHAR 데이터 칼럼끼리 비교할 때 길이가 서로 달라도 공백만 다르다면 같다고 판단함
- VARCHAR(5)일 경우 ‘SQLD’ 저장하면 그대로 ‘SQLD’로 저장됨
- 공백을 주의하여 비교해야 함
ROWNUM
- SQL 예약어로, 데이터가 조회될 때 출력되는 행의 순번을 의미하는 Pseudo 컬럼
- 이 ROWNUM을 WHERE 절의 조건으로 이용하여 결과 행의 건수를 제한할 수 있음.
- SQL 문 조회 시 ROWNUM에 명시한 값만큼만 조회를 하고 조회 연산이 멈춤. 이러한 SQL 문 조회처리를 부분 범위 처리라고 함
함수
단일행 함수
내장 함수 중 입력값에 대해 단 하나의 출력값을 리턴하는 함수를 단일행 함수라고 함
문자형 함수 | 문자 입력 시 문자나 숫자값을 반환 | LOWER, UPPER, SUBSTR, LENGTH, LTRIM, RTRIM, TRIM, ASCII |
숫자형 함수 | 숫자를 입력하면 숫자 값을 반환 | ABS, MOD, ROUND, TRUNC, SIGN, CHR, CEIL, FLOOR, EXP, LOG, LN, POWER, SIN, COS, TAN |
날짜형 함수 | DATE 타입의 값을 연산 | SYSDATE, EXTRACT, TO_NUMBER |
변환형 함수 | 문자, 숫자, 날짜형의 데이터형을 다른 데이터형으로 형변환 | TO_NUMBER, TO_CHAR, TO_DATE, CONVERT |
NULL 관련 함수 | NULL을 처리하기 위한 함수 | NVL, NULLIF, COALESCE |
데이터 형변환의 방식
- 명시적 형변환 : 데이터 형변환 함수로 데이터형을 변환하도록 명시해 주는 경우
SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD'), TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS'), TO_CHAR(10.25, '$999,999,999,99') -- 숫자형을 문자형으로 변환. $10.25 TO_CHAR(12500, 'L999,999,999'), --숫자형을 문자형으로 변환 $12,500
- 암시적 형변환 : DBMS가 자동으로 데이터형을 변환하는 경우
- SQL 문 작성시 문자형과 숫자형을 서로 비교할 때 명시적으로 형변환을 하지 않으면 DBMS 내부에서 자동으로 2개의 각기 다른 데이터형을 동일한 데이터형으로 변환한 후 연산을 처리하게 됨
- 이러한 상황을 “암시적 형변환이 일어났다”고 함
- 암시적 형변환은 인덱스를 정상적으로 스캔하지 못할 수 있기에 명시적 형변환이 좋음!
단일행 CASE 표현의 종류
- 특정 값에 대해서 조건에 따라 각기 다른 값을 리턴하도록 하는 것을 CASE 표현이라고 함
- 이러한 CASE 표현은 CASE 문의 사용 혹은 DECODE 함수를 이용하여 구현할 수 있음
종류 | 설명 |
CASE WHEN 조건
THEN 값 혹은 SQL문
ELSE 값 혹은 SQL문
END | 조건이 맞으면 THEN 절 수행, 그렇지 않으면 ELSE 절 수행 |
DECODE(’조건1, 값1, 조건2, 값2, 디폴트 값) | 조건1이 TRUE면 값1, 조건2 TRUE면 값 2, 그렇지 않으면 디폴트 값 |
SELECT CASE WHEN A.INDUTY_CL_SE_CD = 'ICS001' THEN '대' WHEN A.INDUTY_CL_SE_CD = 'ICS002' THEN '중' WHEN A.INDUTY_CL_SE_CD = 'ICS003' THEN '소' ELSE '' END AS "업종분류구분명" FROM TB_DINTUY_CL_SE A;
NULL 관련함수
- NULLIF(A, B) : A, B 의 문자열이 다르면 첫번째 문자열 출력. 두 문자열이 같다면 NULL을 출력
- NVL(A, B) : A의 값이 NULL이면 B를 출력
- COALESCE(A, B, C) : NULL이 아닌 첫번째 인자를 출력
GROUP BY, HAVING 절
집계함수
집계함수는 데이터를 여러 그룹으로 나누었을 때 각 그룹별로 단 하나의 행을 리턴할 수 있도록 해주는 함수임
COUNT(*) | NULL 값을 포함한 행의 수를 출력함 |
COUNT(표현식) | 표현식의 값이 NULL이 아닌 행의 수를 출력 |
SUM(표현식) | 표현식이 NULL 값인 것을 제외한 합계를 출력 |
AVG(표현식) | 표현식이 NULL 값인 것을 제외한 평균을 출력 |
MAX(표현식) | 표현식이 NULL 값인 것을 제외한 최대값 출력 |
MIN(표현식) | 표현식이 NULL 값인 것을 제외한 최소값을 출력 |
STDDEV(표현식) | 표현식이 NULL 값인 것을 제외한 표준편차를 출력 |
VARIAN(표현식) | 표현식이 NULL 값인 것을 제외한 분산을 출력 |
GROUP BY
GROUP BY 절은 일반적으로 FROM 절 아래에 위치함. GROUP BY 절에 기재한 칼럼을 기준으로 결과집합을 그룹화함
- GROUP BY 절을 통해 소그룹별 기준 칼럼을 정한 후, SELECT 절에서는 집계 함수를 사용함
- 집계 함수의 결과는 NULL 값을 가진 행을 제외하고 수행. GROUP BY 를 적용하는 컬럼 값이 NULL 인 경우는 포함해서 그룹화함
- GROUP BY 절에서는 SELECT 절과는 달리 ALIAS명을 사용할 수 없다.
- GROUP BY 절보다 WHERE 절이 먼저 수행되므로 집계 함수는 WHERE 절에 올 수 없다.
- WHERE 절은 전체 데이터를 GROUP으로 나누기 전에 행들을 필터 처리한다. 즉, WHERE 절에 의해 리턴되는 행들을 대상으로 GROUP BY를 함. 그러므로 집계 함수는 WHERE 절에 올 수가 없는 것임
HAVING 절
- WHERE 절에서는 집계 함수를 쓸 수 없다.
- 집계된 결과집합을 기준으로 특정 조건을 주고 싶은 경우 HAVING 절을 이용한다.
- HAVING 절은 WHERE 절과 비슷하지만 그룹을 나타내는 결과집합의 행에 조건이 적용된다는 점에서 차이가 있다.
- HAVING 절에 들어가는 조건은
GROUP BY절의 기준 항목
이나 소그룹의 집계 함수
가 사용된다.
- GROUP BY 절에 의한 소그룹별로 만들어진 집계 데이터 중, HAVING 절에서 제한 조건을 두어 조건을 만족하는 내용만 출력한다.- HAVING 절은 일반적으로 GROUP BY 절의 뒤에 위치함
- HAVING 절은 WHERE 절과 유사한 기능을 하지만, WHERE 절이 테이블에서 추출할 행을 제한한다고 하면 HAVING 절은 그룹핑한 결과집합에 대한 조건을 주어 추출할 집계 데이터를 제한(필터링)하는 역할을 함
SELECT A.POPLTN_SE_CD, A.AGRDE_SE_CD, SUM(A.POPLTN_CNT) AS "인구수합계" FROM TB_POPLTN A WHERE A.STD_Y = '202010' GROUP BY A.POPLTN_SE_CD, A.AGRDE_SE_CD HAVING SUM(A.POPLTN_CNT) < 1000000;
CASE WHEN 문 사용
- CASE WHEN 문을 이용하여 결과집합을 출력할 때 사용자가 원하는 조건에 따라 분기처리하여 결과집합을 출력할 수 있음
SELECT A.SUBWAY_STATN_NO , SUM(CASE WHEN A.TK_GFF_SE_CD = 'TGS001' THEN A.TK_GFF_CNT ELSE 0 END) AS "승차인원수합계" , SUM(CASE WHEN A.TK_GFF_SE_CD = 'TGS002' THEN A.TK_GFF_CNT ELSE 0 END) AS "하차인원수합계" , SUM(CASE WHEN A.BEGIN_TIME = '0800' AND A.END_TIME = '0900' AND A.TK_GFF_SE_CD = 'TGS001' THEN A.TK_GFF_CNT ELSE 0 END) AS "출근시간대승차인원수합계" , SUM(CASE WHEN A.BEGIN_TIME = '0800' AND A.END_TIME = '0900' AND A.TK_GFF_SE_CD = 'TGS002' THEN A.TK_GFF_CNT ELSE 0 END) AS "출근시간대하차인원수합계" , SUM(CASE WHEN A.BEGIN_TIME = '1800' AND A.END_TIME = '1900' AND A.TK_GFF_SE_CD = 'TGS001' THEN A.TK_GFF_CNT ELSE 0 END) AS "퇴근시간대승차인원수합계" , SUM(CASE WHEN A.BEGIN_TIME = '1800' AND A.END_TIME = '1900' AND A.TK_GFF_SE_CD = 'TGS002' THEN A.TK_GFF_CNT ELSE 0 END) AS "퇴근시간대하차인원수합계" , SUM(TK_GFF_CNT) AS "승하차인원수합계" FROM TB_SUBWAY_STATN_TK_GFF A WHERE A.STD_YM = '202010' GROUP BY A.SUBWAY_STATN_NO HAVING SUM(CASE WHEN A.TK_GFF_SE_CD = 'TGS001' --승차인원수 THEN A.TK_GFF_CNT ELSE 0 END) >= 1000000 OR SUM(CASE WHEN A.TK_GFF_SE_CD = 'TGS002' --하차인원수 THEN A.TK_GFF_CNT ELSE 0 END) >= 1000000 ;
집계 함수와 NULL
- NULL 은 집계 함수의 계산에 포함되지 않고 집계 대상에서 제외됨. COUNT(*) 만이 NULL을 포함해서 갯수를 셈
ORDER BY 절
- NULL의 정렬 — 오라클은 ORDER BY 절에 기재한 칼럼의 값이 NULL이면 가장 큰값이라고 인식함
- ORDER BY 절에 칼럼명 대신에 SELECT 절에서 사용한 앨리어스 명이나 칼럼 순서를 나타내는 정수도 사용 가능함!
- ORDER BY 1 : 첫번째 컬럼 기준으로 정렬
- ORDER BY 시, 컬럼의 필드를 참조해서 정렬하면 그 값 그대로를 정렬하는 것이고 앨리어스 명이나 컬럼 순서 정수를 사용해서 정렬하면 함수가 적용된 값에 대해 정렬하게 됨
SELECT 문의 실행 순서
- SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY 까지 SELECT 문을 구성하는 모든 문법이 나왔음
- SELECT 문 실행 시 오라클 DBMS 내부에서는 아래 순서로 수행을 하게 됨
- FROM 절 — 조회 테이블을 참조함
- WHERE 절 — 조회 대상 행을 조회함
- GROUP BY — 대상 행을 그룹화함
- HAVING — 그룹화한 값에서 조건에 맞는 것을 출력
- SELECT — SELECT 절에 기재한 칼럼이나 식을 계산
- ORDER BY — 출력되는 결과집합을 정렬
SELECT 절에 존재하지 않는 칼럼으로 정렬
- ORDER BY 절을 수행할 때 SELECT 절에 기재하지 않은 칼럼을 기준으로도 정렬이 가능함
SELECT A.SUBWAY_STATN_NO, A.LN_NM, A.STATN_NM FROM TB_SUBWAY_STATN A WHERE A.SUBWAY_STATN_NO = '000607';
GROUP BY 절 사용 시 정렬 작업
- ORDER BY 절 수행 시 SELECT 문에 GROUP BY 절을 사용한 경우 반드시 SELECT 절에 기재한 칼럼 혹은 표현식을 ORDER BY 절에 기재해야 함
- ORDER BY 절에 기재하는 컬럼이 SELECT절에 존재하는 칼럼이나 표현식이 아니라면 에러가 발생함 → not a GROUP BY expression
SELECT A.AGRDE_SE_CD , SUM(A.POPLTN_CNT) AS SUM_POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' --2020년 10월 기준 AND A.POPLTN_SE_CD IN ('M', 'F') --'남', '여' GROUP BY A.AGRDE_SE_CD ORDER BY SUM(A.POPLTN_CNT) DESC ;