Web Programming

SQL

pf333 2021. 6. 14. 23:38

Data Dictionary

 

SELECT * FROM DICT; // 데이터 딕셔너리 조회

DBA_, USER_, ALL_ // 권한

SELECT * FROM USER_TABLES; // USER 권한의 TABLE 조회

SELECT * FROM USER_TAB_COLUMNS; // USER 권한의 TABLE의 COLUMN 조회

SELECT * FROM USER_CONSTRAINTS; // USER 권한의 CONSTRAINT 조회

 

DDL

 

CREATE

 

CREATE TABLE TABLE1(

    COLUMN_NAME DATA_TYPE,

    CONSTRAINT CONSTRAINT1 CHECK(COLUMN1, ~), // CHECK 제약조건 생성

    CONSTRAINT CONSTRAINT2 PRIMARY KEY(COLUMN2), // PRIMARY KEY 제약조건 생성

    CONSTRAINT CONSTRAINT3 UNIQUE(COLUMN3) // UNIQUE 제약조건 생성

    CONSTRAINT CONSTRAINT4 FOREIGN KEY(COLUMN4) REFERENCES 부모 테이블(참조 컬럼) ON OPTION // FOREIGN KEY 제약조건 생성

);

 

CREATE TABLE TABLE1 AS ~ // 컬럼 및 데이터만 생성

 

CREATE SYNONYM TABLE1 FOR A.TABLE1 // SYNONYM 생성

 

// SEQUENCE 생성

CREATE SEQUENCE SEQUENCE1

INCREMENT 1 // 1씩 증가, 생략하면 1씩 증가

START WITH 1; // 1부터 시작, 생략하면 1부터 시작

 

ALTER

 

ALTER TABLE TABLE1 ADD COLUMN1 DATA_TYPE; // 컬럼 추가

ALTER TABLE TABLE1 ADD CONSTRAINT CONSTRAINT1 CONSTRAINT_TYPE; // 제약조건 추가

ALTER TABLE TABLE1 MODIFY COLUMN1 DATA_TYPE CONSTRAINT_TYPE; // 컬럼 데이터 타입, 제약조건 변경

ALTER TABLE TABLE1 DROP COLUMN COLUMN1; // 컬럼 삭제

ALTER TABLE DROP CONSTRAINT CONSTRAINT1; // 제약조건 삭제

 

DROP

 

DROP TABLE TABLE1;

 

TRUNCATE

 

TRUNCATE TABLE TABLE1; // 데이터만 삭제, LOG를 남기지 않아 ROLLBACK이 가능하지 않음

 

DML

 

INSERT

 

INSERT INTO TABLE1(COLUMN1) VALUES(SEQUENCE1.NEXTVAL); // 시퀀스 입력

 

다중 테이블 INSERT

 

1.

INSERT ALL

INTO TABLE1 VALUES(COLUMN1, COLUMN2, ...)

INTO TABLE2 VALUES(COLUMN1, COLUMN2, ...)

SELECT * FROM TABLE3 // TABLE1, 2에 TABLE3의 데이터를 입력

2.

INSERT ALL

WHEN ~ THEN INTO TABLE1 VALUES(COLUMN1, COLUMN2, ...)

WHEN ~ THEN INTO TABLE2 VALUES(COLUMN1, COLUMN2, ...)

ELSE INTO TABLE3 VALUES(COLUMN1, COLUMN2, ...)

SELECT * FROM TABLE4 // 조건에 해당하면 TABLE1, 2에, 조건에 해당하지 않으면 TABLE3에 TABLE4의 데이터를 입력

3.

INSERT FIRST

WHEN ~ THEN INTO TABLE1 VALUES(COLUMN1, COLUMN2, ...)

WHEN ~ THEN INTO TABLE2 VALUES(COLUMN1, COLUMN2, ...)

ELSE INTO TABLE3 VALUES(COLUMN1, COLUMN2, ...)

SELECT * FROM TABLE4 // 첫 번째 테이블에 입력이 되면 두 번째 테이블 이후의 입력을 생략(else if)

 

SELECT

 

SELECT - FROM - WHERE - GROUP BY - HAVING - ORDER BY // 작성 순서

 

FROM - CONNECT BY - WHERE - GROUP BY - HAVING - SELECT - ORDER BY // 실행 순서

별칭은 실행 순서가 뒤인 절에서만 사용 가능(SELECT절에서 지정한 별칭은 ORDER BY절에서만 사용 가능)

 

ROWNUM // SELECT 하여 결과 집합을 만들 때(WHERE절이 실행될 때) 생성, ORDER BY 사용 시 순서가 변경

SELECT * FROM(SELECT ROWNUM, NOTICE.* FROM NOTICE) WHERE ROWNUM BETWEEN 6 AND 10;

// ()외부 SELECT의 ROWNUM이 적용

SELECT * FROM(SELECT ROWNUM NUM, NOTICE.* FROM NOTICE) WHERE NUM BETWEEN 6 AND 10;

// ()내부 SELECT의 ROWNUM이 적용

 

ORDER BY 뒤에 2개 이상의 컬럼을 사용하면 선행 컬럼을 기준으로 후행 컬럼이 정렬

 

DISTINCT 뒤에 2개 이상의 컬럼을 사용하면 DISTINCT 뒤에 오는 모든 컬럼에 대해 하나의 행으로 인식하여 그 행의 중복을 제거

 

JOIN

 

// ANSI INNER JOIN

SELECT * FROM TABLE1 T1 INNER JOIN TABLE2 T2 ON T1.COLUMN1 = T2.COLUMN1

// ORACLE INNER JOIN

SELECT * FROM TABLE1 T1, TABLE2 T2 WHERE T1.COLUMN1 = T2.COLUMN1

 

// ANSI OUTER JOIN

SELECT * FROM TABLE1 T1 LEFT OUTER JOIN TABLE2 T2 ON T1.COLUMN1 = T2.COLUMN1

// ORACLE OUTER JOIN

SELECT * FROM TABLE1 T1, TABLE2 T2 WHERE T1.COLUMN1 = T2.COLUMN1(+)

 

SELECT * FROM TABLE1 T1 LEFT OUTER JOIN TABLE2 T2 PARTITION BY(T2.COLUMN2) ON T1.COLUMN1 = T2.COLUMN1 // T1.COLUMN2 GROUP 후 조인

 

ORACLE SQL의 경우 FULL OUTER JOIN은 지원하지 않음

 

// ANSI CROSS JOIN

SELECT * FROM TABLE1 T1 CROSS JOIN TABLE2 T2 // TABLE1 * TABLE2

// ORACLE CROSS JOIN

SELECT * FROM TABLE1 T1, TABLE2 T2

 

// NATURAL JOIN

SELECT * FROM TABLE1 NATURAL JOIN TABLE2

// 두 테이블의 컬럼명과 데이터 타입이 같은 컬럼을 기준으로 JOIN

SELECT * FROM TABLE1 JOIN TABLE2 USING(COLUMN1, COLUMN2)

// USING절을 사용하여 기준 컬럼 선택 가능, 이때 기준 컬럼 앞에는 테이블명을 명시할 수 없음

 

EXISTS // 교집합

NOT EXISTS // 차집합

// IN/NOT IN으로 대체 가능

 

// ROW를 기준으로 합치는 작업

UNION // 합집합(같은 ROW는 하나만 남김)

MINUS // 차집합

INTERSECT //교집합

UNIONALL // 합집합 + 교집합(같은 ROW도 전부 남김)

// 합쳐지는 컬럼끼리 데이터 타입이 같아야 하며, 첫번째 ALIAS가 적용, UNIONALL을 제외한 나머지 연산에서는 중복 제거를 위해 SORT UNIQUE 연산 추가

 

View

 

// VIEW 생성

CREATE VIEW VIEW1 AS ~

 

// VIEW 조회

SELECT * FROM VIEW1

 

// VIEW 삭제

DROP VIEW VIEW1

 

Subquery

 

스칼라 서브 쿼리(Scalar Subquery) // 한 개의 row당 한 개의 컬럼값을 반환 하는 서브 쿼리(SELECT절에 사용되는 경우가 많음)

인라인 뷰(Inline View) // FROM절에 사용하는 서브 쿼리

중첩 서브 쿼리(Nested Subquery) // WHERE절에 사용하는 서브 쿼리

 

WITH절 // 서브 쿼리에 ALIAS 부여

WITH SQ AS {

    서브 쿼리

}

SELECT * FROM SQ

// 두 번 이상 사용되는 WITH절은 결과값이 temp 영역에 저장되어 디스크 I/O 발생(서브 쿼리의 실행 비용이 큰 경우에만 WITH절을 사용하는 것이 성능상 유리)

Oracle 12.2버전부터는 PGA영역에 저장 후 용량이 부족할 경우에만 temp 영역 사용

 

PIVOT

 

SELECT * FROM(

    SELECT COLUMN1, COLUMN2 FROM TABLE1

) PIVOT(COUNT(*) FOR COLUMN1 IN(VALUE1, VALUE2, VALUE3))

ORDER BY COLUMN2

// SELECT COLUMN2,

COUNT(CASE WHEN COLUMN1 = VALUE1 THEN 1 END) AS VALUE1,

COUNT(CASE WHEN COLUMN1 = VALUE2 THEN 1 END) AS VALUE2,

COUNT(CASE WHEN COLUMN1 = VALUE3 THEN 1 END) AS VALUE3

FROM TABLE1

GROUP BY COLUMN2

ORDER BY COLUMN2

 

UPDATE

 

UPDATE TABLE1 SET COLUMN1 = VALUE1 WHERE ~

 

UPDATE TABLE1 SET(COLUMN1, COLUMN2, COLUMN3) = (SELECT VALUE1, VALUE2, VALUE3) WHERE ~

 

UPDATE TABLE1 SET COLUMN1 = CASE WHEN ~ THEN 'V1' WHEN ~ THEN 'V2' ELSE 'V3' END

 

MERGE INTO TABLE1 T1

USING TABLE2 T2

ON T1.COLUMN1 = T2.COLUMN1

WHEN MATCHED THEN

    UPDATE SET ~

    DELETE WHERE ~

WHEN NOT MATCHED THEN

    INSERT ~ VALUES ~

 

DELETE

 

DELETE FROM TABLE1

 

데이터 복구

 

SHOW PARAMETER UNDO_RETENTION // UNDO_RETENTION 반환(초 단위)

 

INSERT INTO TABLE1

SELECT * FROM TABLE1

AS OF TIMESTAMP(SYSTIMESTAMP - INTERVAL '15' MINITE)

WHERE ~

 

TRIGGER

 

CREATE OR REPLACE TRIGGER TRIGGER1

AFTER INSERT OR UPDATE OR DELETE ON TABLE1

FOR EACH ROW

BEGIN

    IF INSERTING THEN

        INSERT INTO TABLE2 VALUES(:NEW.COLUMN1, :NEW.COLUMN2, SYSDATE)

    END IF;

 

    IF UPDATING THEN

        ~

    END IF; // :OLD를 사용하여 변경 전 데이터 사용 가능

 

    IF DELETING THEN

        ~

    END IF;

END;

 

DCL

// GRANT, REVOKE

 

Built-In Datatypes

 

Character 형식

 

CHAR(N), CHAR(N CHAR) // 고정 길이 데이터에 적합, 가변 길이 데이터를 사용할 때는 공간이 낭비되는 경우가 많다.

VARCHAR2(N), VARCHAR2(N CHAR)  // 가변 길이 데이터에 적합, 검색하는데 시간이 오래 걸린다.

N인 경우 byte, N CHAR인 경우 문자 길이, 영어 1byte, 한글 3byte

NCHAR(N), NVARCHAR2(N) // 다국어 데이터에 적합, N은 문자 길이, 영어, 한글 모두 2byte

최대 4000byte까지 사용 가능

CLOB // 대용량 텍스트 데이터 타입(최대 4GB)

NCLOB // 대용량 텍스트 유니코드 데이터 타입(최대 4GB)

 

Numeric 형식

 

NUMBER // NUMBER(38, *), 최대 38자리까지 사용 가능

NUMBER(N) // 최대 N자리까지 사용 가능

NUMBER(N, M) // 소수 M번째 자리까지 반올림하여 최대 N자리까지 사용 가능

 

Date 형식

 

DATE // 날짜 표현

TIMESTAMP // 날짜, 시간 표현

 

연산자

 

산술 연산자

 

숫자 + 문자 = 숫자 // +는 숫자 덧셈 기호

숫자 || 문자 = 문자 // ||는 문자열 덧셈 기호

 

논리 연산자

 

AND 연산자가 OR 연산자보다 우선순위가 높음

A OR B AND C는  A OR (B AND C)와 같이 연산

 

비교 연산자

 

^=(ORACLE), <>(ANSI) // !=

 

패턴 비교 연산자

 

_ // 한 자릿수

LIKE '김_' // 김씨 중 이름이 외자인 사람

 

정규식

 

[] // 하나의 문자 표현

[09] // 0 or 9

[0-9], \d // 0 ~ 9

01[016-9]-\d\d\d\d-\d\d\d\d

 

{} // 반복횟수

01[016-9]-\d{3, 4}-\d{4}

 

^ // 시작

$ // 끝

^01[016-9]-\d{3, 4}-\d{4}$

 

REGEXP_LIKE(COLUMN_NAME, PATTERN) // 정규식 사용 시 사용되는 함수

REGEXP_LIKE(PHONE, '^01[016-9]-\d{3, 4}-\d{4}$') // 형식과 일치하는 경우

REGEXP_LIKE(PHONE, '01[016-9]-\d{3, 4}-\d{4}') // 형식이 포함된 경우

 

\w // [a-zA-Z_0-9]

* // 0자 이상

+ // 1자 이상

? // 0자 또는 1자

| // 문자열 구분

\D, [^0-9]  // 0-9가 아닌 것

\D\w*@\D\w*.(org|net|com)

 

REGEXP_LIKE(EMAIL, '^\D\w*@\D\w*.(org|net|com)$')

 

함수

 

문자열 함수

 

// 문자열 추출 함수

SUBSTR(문자열, 시작위치)

SELECT SUBSTR('HELLO', 3) FROM DUAL; // LLO

SUBSTR(문자열, 시작위치, 길이)

SELECT SUBSTR('HELLO', 3, 2) FROM DUAL; // LL

SUBSTRB(문자열, 시작위치), SUBSTRB(문자열, 시작위치, 길이) // byte 단위 조회

 

CONCAT(문자열, 문자열) // 문자열 덧셈 함수, 문자열 || 문자열

 

// 문자열 트림 함수

LTRIM(문자열) // 왼쪽 공백 제거

RTRIM(문자열) // 오른쪽 공백 제거

TRIM(문자열) // 양쪽 공백 제거

 

LOWER(문자열) // 문자열 소문자로 변경 함수

UPPER(문자열) // 문자열 대문자로 변경 함수

 

// 문자열 대치 함수

REPLACE(문자열, 찾는 문자열, 대치할 문자열)

SELECT REPLACE('HELLO WORLD', 'WORLD', 'SQL') FROM DUAL; // HELLO SQL

SELECT REPLACE('HELLO WORLD'', ' ', '') FROM DUAL; // HELLOWORLD

 

TRANSLATE(문자열, 찾는 문자, 대치할 문자)

SELECT TRANSLATE('HELLO WORLD', 'WORLD', 'SQL') FROM DUAL;

// HELLQ SQLLD, W를 S로, O를 Q로, R을 L로 변경

 

// 문자열 패딩 함수

LPAD(문자열, byte, 패딩 문자) 

SELECT LPAD('HELLO', 10, 0) FROM DUAL; // 00000HELLO

RPAD(문자열, byte, 패딩 문자)

SELECT RPAD('HELLO', 10, 0) FROM DUAL; // HELLO00000

LPAD(문자열, byte), RPAD(문자열, byte) // 패딩 문자가 공백

 

INITCAP(문자열) // 첫 글자를 대문자로 바꾸는 함수

SELECT INITCAP('hello world') FROM DUAL; // Hello World

 

// 문자열 검색 함수

INSTR(문자열, 검색 문자열)

SELECT INSTR('HELLO', 'L') FROM DUAL; // 3, 첫 번째 위치부터 시작하여 나오는 첫 번째 L이 몇 번째 문자인지 반환

INSTR(문자열, 검색 문자열, 위치)

SELECT INSTR('HELLO', 'L', 4) FROM DUAL; // 4, 네 번째 위치부터 시작하여 나오는 첫 번째 L이 몇 번째 문자인지 반환

INSTR(문자열, 검색 문자열, 위치, 찾을 수)

SELECT INSTR('HELLO', 'L', 1, 2) FROM DUAL; // 4, 첫 번째 위치부터 시작하여 나오는 두 번째 L이 몇 번째 문자인지 반환

 

LENGTH(문자열) // 문자열 길이를 반환하는 함수

LENGTHB(문자열) // byte 길이를 반환하는 함수

 

ASCII(문자) // 코드값을 반환하는 함수

SELECT ASCII('A') FROM DUAL; // 65

 

CHR(코드 값) // 문자를 반환하는 함수

SELECT CHR(65) FROM DUAL; // A

 

숫자 함수

 

ABS(N) // 절대값을 반환하는 함수 

SELECT ABS(35), ABS(-35) FROM DUAL; // 35, 35

 

SIGN(N) // 음수/양수를 알려주는 함수 

SELECT SIGN(35), SIGN(-35), SIGN(0); // 양수는 1, 음수는 -1, 0은 0

 

// 반올림 값을 반환하는 함수

ROUND(N)

SELECT ROUND(34.456789), ROUND(34.56789) FROM DUAL; // 34, 35

ROUND(N, I)

SELECT ROUND(12.3456789, 2), ROUND(12.3456789, 3) // 12.35, 12.346

 

// 버림 값을 반환하는 함수

TRUNK(N)

SELECT TRUNK(17/5) FROM DUAL; // 3

TRUNK(N, I)

SELECT TRUNK(57.39, 1) FROM DUAL // 57.3

SELECT TRUNK(57.39, -1) FROM DUAL // 50

 

MOD(N1, N2) // 나머지를 반환하는 함수

SELECT MOD(17, 5) FROM DUAL; // 2

 

POWER(N1, N2) // 제곱을 반환하는 함수

SELECT POWER(5, 2) FROM DUAL; // 25

SQRT(N) // 제곱근을 반환하는 함수

SELECT SQRT(25) FROM DUAL; // 5

 

GREATEST(N1, N2, N3, ...) // 최댓값을 반환하는 함수

SELECT GREATEST(1, 2, 3, 4, 5) FROM DUAL; // 5

SELECT GREATEST(1, 2, 3, 4, null) FROM DUAL; // null 반환

LEAST(N1, N2, N3, ...) //최솟값을 반환하는 함수

SELECT LEAST(1, 2, 3, 4, 5) FROM DUAL; // 1

 

날짜 함수

 

// 현재 시간을 반환하는 함수

// DBMS의 시간

SYSDATE // 연월일시분초

SYSTIMESTAMP // 연월일시분초+밀리세컨드

// 사용자 세션의 시간

CURRENT_DATE // 연월일시분초

CURRENT_TIMESTAMP // 연월일시분초+밀리세컨드

 

// 세션 시간대와 포맷 변경

ALTER SESSION SET TIME_ZONE = '09:00'

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'

 

EXTRACT(YEAR/MONTH/DAY/HOUR/MINUTE/SECOND FROM ...) // 날짜 추출 함수

SELECT EXTRACT(YEAR FROM SYSDATE) FROM DUAL;

 

ADD_MONTH(날짜, 정수) // 날짜를 누적하는 함수

SELECT ADD_MONTHS(SYSDATE, 1) FROM DUAL;

SELECT ADD_MONTHS(SYSDATE, -1) FROM DUAL;

 

MONTHS_BETWEEN(날짜, 날짜) // 날짜의 차이를 반환하는 함수

SELECT MONTHS_BETWEEN (SYSDATE, TO_DATE('2013-12-25')) FROM DUAL;

 

NEXT_DAY(현재 날짜, 다음 요일) // 다음 요일에 해당하는 날짜를 반환하는 함수

SELECT NEXT_DAY(SYSDATE, '토') FROM DUAL;

SELECT NEXT_DAY(SYSDATE, '토요일') FROM DUAL;

SELECT NEXT_DAY(SYSDATE, 7) FROM DUAL;

 

LAST_DAY(날짜) // 월의 마지막 날짜를 알려주는 함수 

SELECT LAST_DAY(SYSDATE) FROM DUAL;

 

// 지정된 범위에서 날짜를 반올림하는/자르는 함수

ROUND(날짜, 형식), TRUNK(날짜, 형식)

CC, YEAR, Q, MONTH, W, DAY, HH, MI // 세기, 연, 분기, 월, 주, 일 ,시, 분

SELECT ROUND(SYSDATE, 'DAY') FROM DUAL; // 시간이 정오 이후이면 내일 날짜, 이전 이면 오늘 날짜

SELECT TRUNK(SYSDATE, 'DAY') FROM DUAL; // 오늘 날짜(시간 제외)

ROUND(날짜), TRUNK(날짜) // ROUND(날짜, 'DAY'), TRUNK(날짜, 'DAY')

 

변환 함수

 

// NUMBER 형식을 문자열(VARCHAR2)로 변환

TO_CHAR(NUMBER)

TO_CHAR(NUMBER, 형식)

TO_CHAR(12345678.90, '$099,999,999.99') // $012,345,678.90

9, 0 // 숫자, 빈 자리를 채우는 문자

왼쪽 변환 대상을 오른쪽 형식에 맞추어 변환한다. 변환 대상의 자릿수와 형식의 자릿수가 같거나 변환 대상의 자릿수보다 형식의 자릿수가 더 커야한다. 형식의 자릿수가 더 큰 경우 형식 앞에 0이 있으면 나머지 자리는 0으로 변환되고 형식 앞에 0이 없으면 나머지 자리가 공백으로 변환된다.

소수점에서 0과 9의 의미는 같다. 변환 대상의 소수점 자릿수가 형식의 소수점 자릿수 보다 더 큰 경우 형식에서 0과 9는 숫자의 의미를 가지며 형식의 소수점 자릿수에 맞추어 반올림 되어 변환된다. 변환 대상의 소수점 자릿수가 형식의 소수점 자릿수 보다 더 작은 경우 형식에서 0과 9는 빈 자리를 채우는 문자의 의미를 가지며 나머지 자리는 0으로 변환된다.

 

// DATE 형식을 문자열(VARCHAR2)로 변환

TO_CHAR(DATETIME)

TO_CHAR(DATETIME, 형식)

TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:MI:SS')

 

TO_DATE(문자열) // 문자열을 DATE 형식으로 변환하는 함수 

TO_DATE(문자열, 형식) // 문자열이 NLS_DATE_FORMAT이 아닌 경우 형식 설정

TO_DATE(SYSDATE, 'YYYY-MM-DD HH:MI:SS')

TO_TIMESTAMP(문자열) // 문자열을 TIMESTAMP 형식으로 변환하는 함수 

TO_TIMESTAMP(문자열, 형식) // 문자열이 NLS_TIMESTAMP_FORMAT이 아닌 경우 형식 설정

TO_TIMESTAMP(SYSTIMESTAMP, 'YYYY-MM-DD HH:MI:SS')

 

TO_NUMBER(문자열) // 문자열을 NUMBER 형식으로 변환하는 함수 

 

NULL 관련 함수

 

NVL(입력값, 대체값) // 입력값이 NULL일 경우에 대체값을 제공하는 함수

SELECT NVL(AGE, 0) FROM MEMBERS;

 

NVL2(입력값, NOT NULL 대체값, NULL 대체값) // 입력값이 NOT NULL, NULL일 경우에 대체값을 제공하는 함수

SELECT NVL2(AGE, 100/AGE, 0) FROM MEMBERS;

 

NULLIF(입력값1, 입력값2) // 두 값이 같은 경우 NULL, 그렇지 않은 경우 첫 번째 값을 반환하는 함수

SELECT NULLIF(AGE, 19) FROM MEMBERS;

 

COALESCE(입력값1, 입력값2, ..., 입력값N) // NULL이 아닌 최초의 값을 출력

 

DECODE(입력값, 비교값1, 출력값1, 비교값2, 출력값2, ..., 비교값이 아닌 경우 출력값) // 조건에 따른 값 선택하기 

SELECT DECODE(SUBSTR(PHONE, 1, 3),

'011', 'SK',

'016', 'KT',

'기타') FROM MEMBERS;

SELECT CASE COLUMN1 WHEN 'A' THEN 'B' WHEN 'C' THEN 'D' ELSE 'E' END FROM TABLE1

SELECT CASE WHEN COLUMN1 = 'A' THEN 'B' WHEN COLUMN1 = 'C' THEN 'D' ELSE 'E' END FROM TABLE1

 

집계 함수

 

COUNT()

 

SELECT COUNT(COLUMN_NAME) FROM TABLE_NAME // NULL 제외 개수

SELECT COUNT(*) FROM TABLE_NAME // NULL 포함 개수

 

ROW_NUMBER()

 

ROW_NUMBER() // 정렬 이후 ROWNUM을 붙일 때 사용

SELECT ROW_NUMBER() OVER(ORDER BY HIT) FROM NOTICE; // HIT을 기준으로 정렬하고 ROWNUM을 붙인다.

 

SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY REGDATE DESC) NUM, NOTICE.* FROM NOTICE)

WHERE NUM BETWEEN 6 AND 10;

=

SELECT * FROM(SELECT ROWNUM NUM, N.* FROM (SELECT * FROM NOTICE ORDER BY REGDATE DESC) N)

WHERE NUM BETWEEN 6 AND 10;

 

SELECT ROW_NUMBER() OVER(PARTITION BY WRITER_ID ORDER BY HIT) FROM NOTICE; // WRITER_ID를 기준으로 그룹화(이때 WRITER_ID를 기준으로 오름차순 정렬)한 후 HIT을 기준으로 정렬하고 ROWNUM을 붙인다.

 

RANK(), DENSE_RANK()

 

SELECT RANK() OVER(ORDER BY HIT) FROM NOTICE; // HIT을 기준으로 정렬하고 순위를 매긴다.(공동 순위가 있으면 다음 순위 생략)

SELECT DENSE_RANK() OVER(ORDER BY HIT) FROM NOTICE; // HIT을 기준으로 정렬하고 순위를 매긴다.(공동 순위가 있어도 다음 순위 인정)

SELECT DENSE_RANK() OVER(PARTITION BY WRITER_ID ORDER BY HIT) FROM NOTICE; // WRITER_ID를 기준으로 그룹화(이때 WRITER_ID를 기준으로 오름차순 정렬)한 후 HIT을 기준으로 정렬하고 순위를 매긴다.

 

PERCENT_RANK()

 

(RANK - 1) / (TOTAL_ROWS - 1)

 

ROLLUP()

 

SELECT COLUMN1, COUNT(*) FROM TABLE GROUP BY ROLLUP(COLUMN1) // GROUP BY COLUMN1 합계 + 총 합계

 

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY ROLLUP(COLUMN1, COLUMN2) // GROUP BY COLUMN1, COLUMN2 합계 + GROUP BY COLUMN1 합계 + 총 합계

 

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY ROLLUP((COLUMN1, COLUMN2)) // GROUP BY COLUMN1, COLUMN2 합계 + 총 합계

 

CUBE()

 

SELECT COLUMN1, COUNT(*) FROM TABLE GROUP BY CUBE(COLUMN) // GROUP BY COLUMN1 합계 + 총 합계

 

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY CUBE(COLUMN1, COLUMN2);

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY CUBE(COLUMN2, COLUMN1);

(ROLLUP 함수와 달리 컬럼의 순서가 결과에 영향을 주지 않는다.)

// SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY COLUMN1, COLUMN2

UNION ALL

SELECT COLUMN1, NULL, COUNT(*) FROM TABLE GROUP BY COLUMN1

UNION ALL

SELECT NULL, COLUMN2, COUNT(*) FROM TABLE GROUP BY COLUMN2

UNION ALL

SELECT NULL, NULL, COUNT(*) FROM TABLE

ORDER BY 1, 2;

 

NTILE()

 

SELECT NTILE(N) OVER(ORDER BY COLUMN1) FROM TABLE1 // 대상 데이터를 N만큼 분할하여 N개의 숫자 부여, 대상 데이터가 N개 초과 시 1부터 중복 부여

 

제약조건

 

도메인 // 유효한 값의 범위

도메인 제약조건 // COLUMN에 도메인이 아닌 값이 올 수 없도록 하는 제약조건

NOT NULL 제약조건, DEFAULT 제약조건, CHECK 제약조건

 

엔티티 제약조건 // 테이블에 중복된 ROW가 없도록 하는 제약조건

PRIMARY KEY // 한 개만 설정 가능, NOT NULL, 중복X, UNIQUE INDEX 생성

UNIQUE // 두 개 이상 설정 가능, NULL 허용, 중복 X, UNIQUE INDEX 생성

FOREIGN KEY // 부모 테이블의 참조 컬럼은 PK나 UK, 참조 컬럼과 데이터 타입 및 내용이 일치해야 함

// OPTION(DELETE/UPDATE ~)


1. 학습 안내(SQL, DB, DBMS의 의미와 필요성)

 

SQL(Structured Query Language): DBMS에게 (구조화된 데이터를)질의하는 명령어

 

DBMS: '동시성, 성능, 보안' 문제 해결

 

DDL: CREATE/ALTER/DROP

DML: INSERT/SELECT/UPDATE/DELETE

DCL: GRANT/REVOKE

 

2. 오라클 DBMS 18c XE 설치하기

 

SQLPLUS 접속

사용자명: sys as sysdba

비밀번호:

 

3. SQL Developer 설치하기

 

4. 오라클 PDB 서버에 접속하기

 

PDB(가상 데이터베이스) 접속

select name from v$pdbs; // pluggable database 확인

SID: xe(CDB)에서 서비스 이름: xepdb1(PDB)으로 변경

 

원격 접속을 위한 설정 변경

EXEC DBMS_XDB.SETLISTENERLOCALACCESS(FALSE);

호스트 이름을 데이터베이스가 설치되어 있는 pc의 ip로 변경

 

5. 수업용 사용자와 데이터베이스 생성하기

 

DBA 접속 - 저장 영역 - 테이블 스페이스 생성(기본, 임시)

                - 보안 - 사용자 생성

 

6. MEMBER 테이블 생성하기

 

CREATE TABLE MEMBER(

    NAME VARCHAR2(50),

    AGE NUMBER,

    REGDATE DATE

);

 

7. 오라클 데이터 형식 #1 (문자 형식)

 

Oracle Built-In Datatypes

Character 형식

문자를 나타낼 때 홑따옴표(') 사용

 

CHAR(N), CHAR(N CHAR) // 고정 길이 데이터에 적합, 가변 길이 데이터를 사용할 때는 공간이 낭비되는 경우가 많다.

VARCHAR2(N), VARCHAR2(N CHAR)  // 가변 길이 데이터에 적합, 검색하는데 시간이 오래 걸린다.

N인 경우 byte, N CHAR인 경우 문자 길이, 영어 1byte, 한글 3byte

NCHAR(N), NVARCHAR2(N) // 다국어 데이터에 적합, N은 문자 길이, 영어, 한글 모두 2byte

최대 4000byte까지 사용 가능

LENGTH() // 문자 길이

LENGTHB() // byte 길이

 

8. 오라클 데이터 형식 #2 (숫자, 날짜 형식)

 

LONG // 한 TABLE당 한 개의 COLUMN에만 사용 가능(최대 2GB), 최근에는 잘 사용하지 않는다.

CLOB // 대용량 텍스트 데이터 타입(최대 4GB)

NCLOB // 대용량 텍스트 유니코드 데이터 타입(최대 4GB)

 

Numeric 형식

NUMBER // NUMBER(38, *), 최대 38자리까지 사용 가능

NUMBER(N) // 최대 N자리까지 사용 가능

NUMBER(N, M) // 소수 M번째 자리까지 반올림하여 최대 N자리까지 사용 가능

 

Date 형식

DATE // 날짜 표현

TIMESTAMP // 날짜, 시간 표현

지역 정보 확인

SELECT * FROM NLS_DATABASE_PARAMETERS

 

9. 테이블 수정하기(ALTER TABLE)

 

ALTER TABLE MEMBER MODIFY ID NVARCHAR2(20);

ALTER TABLE MEMBER DROP COLUMN AGE;

ALTER TABLE MEMBER ADD EMAIL VARCHAR2(200);

 

10. SQL 쿼리 연습 테이블 준비하기

 

부적합한 테이블명, 컬럼명(예약어, 공백을 포함한 경우 등)은 "로 감싸서 입력한다.

 

11. 데이터 조작하기 #1 (SELECT/INSERT)

 

명령어, 컬럼명은 대소문자 구분을 하지 않는다.

 

EXISTS // 교집합

NOT EXISTS// 차집합

// IN/NOT IN으로 대체 가능

 

SELECT CASE COLUMN1 WHEN 'A' THEN 'B' WHEN 'C' THEN 'D' ELSE 'E' END FROM TABLE1

SELECT CASE WHEN COLUMN1 = 'A' THEN 'B' WHEN COLUMN1 = 'C' THEN 'D' ELSE 'E' END FROM TABLE1

 

다중 테이블 INSERT

 

1.

INSERT ALL

INTO TABLE1 VALUES(COLUMN1, COLUMN2, ...)

INTO TABLE2 VALUES(COLUMN1, COLUMN2, ...)

SELECT * FROM TABLE3 // TABLE1, 2에 TABLE3의 데이터를 입력

2.

INSERT ALL

WHEN ~ THEN INTO TABLE1 VALUES(COLUMN1, COLUMN2, ...)

WHEN ~ THEN INTO TABLE2 VALUES(COLUMN1, COLUMN2, ...)

ELSE INTO TABLE3 VALUES(COLUMN1, COLUMN2, ...)

SELECT * FROM TABLE4 // 조건에 해당하면 TABLE1, 2에, 조건에 해당하지 않으면 TABLE3에 TABLE4의 데이터를 입력

3.

INSERT FIRST

WHEN ~ THEN INTO TABLE1 VALUES(COLUMN1, COLUMN2, ...)

WHEN ~ THEN INTO TABLE2 VALUES(COLUMN1, COLUMN2, ...)

ELSE INTO TABLE3 VALUES(COLUMN1, COLUMN2, ...)

SELECT * FROM TABLE4 // 첫 번째 테이블에 입력이 되면 두 번째 테이블 이후의 입력을 생략(else if)

 

12. 데이터 조작하기 #2 (UPDATE/DELETE)

 

MERGE INTO TABLE1 T1

USING TABLE2 T2

ON T1.COLUMN1 = T2.COLUMN1

WHEN MATCHED THEN

    UPDATE SET ~

    DELETE WHERE ~

WHEN NOT MATCHED THEN

    INSERT ~ VALUES ~

 

TRUNCATE TABLE TABLE_NAME; // 테이블 초기화, ROLLBACK 불가능

 

13. 트랜잭션 처리를 위한 COMMIT과 ROLLBACK

 

트랜잭션: 업무 실행 단위, 논리적인 명령 단위

 

작업 중이면 LOCK이 걸리고 COMMIT이나 ROLLBACK이 되어야 UNLOCK이 된다.

 

14. 연산을 통한 데이터 조회(산술 연산자)

 

DUAL // 더미테이블

숫자 + 문자 = 숫자(다른 언어에서 숫자 + 문자 = 문자인 것과 차이가 있음) // +는 숫자 덧셈 기호

|| 문자열 덧셈 기호

숫자 || 문자 = 문자

 

15. 비교 연산자

 

!=, ^=(oracle), <>(ansi) // 같지 않다는 의미

 

16. 관계 연산자

 

BETWEEN N AND M: N이상 M이하

 

17. 패턴 비교 연산자

 

LIKE '박_': 박씨 중 이름이 외자인 사람

_: 자릿수 한정

 

18. 정규식을 이용한 패턴 비교

 

[]: 하나의 문자 표현

[016789]: 0 or 1 or 6 or 7 or 8 or 9

[0-9], \d: 0~9

01[016-9]-\d\d\d\d-\d\d\d\d

 

{}: 반복횟수

01[016-9]-\d{3, 4}-\d{4}

 

^ // 시작

$ // 끝

^01[016-9]-\d{3, 4}-\d{4}$ // 정확하게 ^$ 사이에 있는 형식, ^$가 없으면 해당 형식이 포함되기만 하면 되는 경우

 

REGEXP_LIKE(COLUMN, PATTERN): 정규식 사용 시 사용되는 함수

REGEXP_LIKE(PHONE, 01[016-9]-\d{3, 4}-\d{4})

 

19. 문자열 비교를 위한 정규식

 

\w // [a-zA-Z_0-9]

* // 0자 이상

+ // 1자 이상

? // 0자 또는 1자

| // 문자열 구분

\D, [^0-9]  // 0-9가 아닌 것

\D\w*@\D\w*.(org|net|com)

 

20. ROWNUM 그리고 행 제한하기

 

ROWNUM: SELECT 하여 결과 집합을 만들 때 생성

SELECT * FROM(SELECT ROWNUM, NOTICE.* FROM NOTICE) WHERE ROWNUM BETWEEN 6 AND 10;

()바깥 부분의 ROWNUM이 적용된다.

SELECT * FROM(SELECT ROWNUM NUM, NOTICE.* FROM NOTICE) WHERE NUM BETWEEN 6 AND 10;

()안쪽 부분의 ROWNUM이 적용된다.

 

21. 중복 값 제거하기 DISTINCT

 

하나의 컬럼을 조회할 때만 사용 가능

 

22. 중간 요약과 함수 단원 안내

 

23. 문자열 내장 함수 #1

 

// 문자열 추출 함수 

SUBSTR(문자열, 시작위치, 길이)

SELECT SUBSTR('HELLO', 1, 3) FROM DUAL; // HEL

SUBSTR(문자열, 시작위치)

SELECT SUBSTR('HELLO', 3) FROM DUAL; // LLO

SUBSTRB(문자열, 시작위치, 길이), SUBSTRB(문자열, 시작위치) // byte 단위 조회

SELECT SUBSTRB('HELLO', 3) FROM DUAL; // LLO 

 

CONCAT(문자열, 문자열) // 문자열 덧셈 함수, 문자열 || 문자열

 

// 문자열 트림 함수

LTRIM(문자열) // 왼쪽 공백 제거

RTRIM(문자열) // 오른쪽 공백 제거

TRIM(문자열) // 양쪽 공백 제거

 

// 문자열 소문자 또는 대문자로 변경 함수

LOWER(문자열) // 문자열 소문자로 변경 함수

UPPER(문자열) // 문자열 대문자로 변경 함수

 

// 문자열 대치 함수

SELECT REPLACE(문자열, 찾는 문자열, 대치할 문자열) FROM DUAL;

SELECT REPLACE('WHERE WE ARE', 'WE', 'YOU') FROM DUAL; // WHERE YOU ARE

SELECT REPLACE('WHERE WE ARE', ' ', '') FROM DUAL; // WHEREWEARE(\n 제거 시 CHR(10))

 

SELECT TRANSLATE(문자열, 찾는 문자, 대치할 문자) FROM DUAL;

SELECT TRANSLATE('WHERE WE ARE', 'WE', 'YOU') FROM DUAL; // W를 Y로, E를 O로 변경, 'YHORO YO ARO'

 

24. 문장열 내장 함수 #2

 

// 문자열 패딩 함수

LPAD(문자열, 길이, 패딩 문자) // byte 단위 조회

SELECT LPAD('HELLO', 10, 0) FROM DUAL; // 00000HELLO

RPAD(문자열, 길이, 패딩 문자)

SELECT RPAD('HELLO', 10, 0) FROM DUAL; // HELLO00000

LPAD(문자열, 길이), RPAD(문자열, 길이) // 패딩 문자가 공백

한글인 경우 길이가 글자 수 * 2

 

INITCAP(문자열) // 첫 글자를 대문자로 바꾸는 함수

SELECT INITCAP('hello world') FROM DUAL; // Hello World

 

INSTR(문자열, 검색 문자열, 위치, 찾을 수) // 문자열 검색 함수

SELECT INSTR('HELLO', 'L') FROM DUAL; // 3, 첫 번째 위치부터 시작하여 첫 번째 L이 몇 번째 문자인지 반환

SELECT INSTR('HELLO', 'L', 4) FROM DUAL; // 4, 네 번째 위치부터 시작하여 나오는 L이 몇 번째 문자인지 반환

SELECT INSTR('HELLO', 'L', 1, 2) FROM DUAL; // 4, 첫 번째 위치부터 시작하여 두 번째 L이 몇 번째 문자인지 반환

 

LENGTH(문자열) // 문자열 길이를 얻는 함수

 

ASCII(문자) // 코드값을 반환하는 함수

SELECT ASCII('A') FROM DUAL; // 65

 

CHR(코드 값) // 코드 값으로 문자를 반환하는 함수

SELECT CHR(65) FROM DUAL; // A

 

25. 숫자 내장 함수

 

ABS(N) // 절대값을 반환하는 함수 

SELECT ABS(35), ABS(-35) FROM DUAL; // 35, 35

 

SIGN(N) // 음수/양수를 알려주는 함수 

SELECT SIGN(35), SIGN(-35), SIGN(0); // 양수는 1, 음수는 -1, 0은 0

 

// 숫자의 반올림 값을 반환하는 함수

ROUND(N)

SELECT ROUND(34.456789), ROUND(34.56789) FROM DUAL; // 34, 35

ROUND(N, I)

SELECT ROUND(12.3456789, 2), ROUND(12.3456789, 3) // 12.35, 12.346

 

// 숫자의 버림값을 반환하는 함수

TRUNK(N)

SELECT TRUNK(17/5) FROM DUAL; // 3

TRUNK(N, I)

SELECT TRUNK(57.39, 1) FROM DUAL // 57.3

SELECT TRUNK(57.39, -1) FROM DUAL // 50

 

MOD(N1, N2) // 숫자의 나머지를 반환하는 함수

SELECT MOD(17, 5) FROM DUAL; // 2

 

POWER(N1, N2) // 숫자의 제곱을 반환하는 함수

SELECT POWER(5, 2) FROM DUAL; // 25

SQRT(N) // 숫자의 제곱근을 반환하는 함수

SELECT SQRT(25) FROM DUAL; // 5

 

GREATEST(N1, N2, N3, ...) // 최댓값을 반환하는 함수

SELECT GREATEST(1, 2, 3, 4, 5) FROM DUAL; // 5

SELECT GREATEST(1, 2, 3, 4, null) FROM DUAL; // null 반환

LEAST(N1, N2, N3, ...) //최솟값을 반환하는 함수

SELECT LEAST(1, 2, 3, 4, 5) FROM DUAL; // 1

 

26. 날짜 함수

 

// 현재 시간을 얻는 함수

// DBMS의 시간

SYSDATE // 연월일시분초

SYSTIMESTAMP // 연월일시분초+밀리세컨드

// 사용자의 세션 시간

CURRENT_DATE // 연월일시분초

CURRENT_TIMESTAMP // 연월일시분초+밀리세컨드

 

세션 시간과 포맷 변경

ALTER SESSION SET TIME_ZONE = '09:00'

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'

 

EXTRACT(YEAR/MONTH/DAY/HOUR/MINUTE/SECOND FROM ...) // 날짜 추출 함수

SELECT EXTRACT(YEAR FROM SYSDATE) FROM DUAL; // 년

SELECT EXTRACT(MONTH FROM SYSDATE) FROM DUAL;

SELECT EXTRACT(DAY FROM SYSDATE) FROM DUAL;

SELECT EXTRACT(MINUTE FROM SYSDATE) FROM DUAL;

SELECT EXTRACT(SECOND FROM SYSDATE) FROM DUAL;

 

ADD_MONTH(날짜, 정수) // 날짜를 누적하는 함수

SELECT ADD_MONTHS(SYSDATE, 1) FROM DUAL; // 한 달 이후

SELECT ADD_MONTHS(SYSDATE, -1) FROM DUAL; // 한 달 이전

 

MONTHS_BETWEEN(날짜, 날짜) // 날짜의 차이를 알아내는 함수

SELECT MONTHS_BETWEEN (SYSDATE, TO_DATE('2013-12-25')) FROM DUAL;

 

NEXT_DAY(현재 날짜, 다음 요일) // 다음 요일에 해당하는 날짜를 알려주는 함수

SELECT NEXT_DAY(SYSDATE, '토') FROM DUAL;

SELECT NEXT_DAY(SYSDATE, '토요일') FROM DUAL;

SELECT NEXT_DAY(SYSDATE, 7) FROM DUAL;

 

LAST_DAY(날짜) // 월의 마지막 날짜를 알려주는 함수 

SELECT LAST_DAY(SYSDATE) FROM DUAL; // SYSDATE이 속한 달의 마지막 날짜

 

// 지정된 범위에서 날짜를 반올림하는/자르는 함수

ROUND(날짜, 형식), TRUNK(날짜, 형식)

SELECT ROUND(SYSDATE, 'CC'), TRUNK(SYSDATE, 'CC') FROM DUAL; // 세기

SELECT ROUND(SYSDATE, 'YEAR'), TRUNK(SYSDATE, 'YEAR') FROM DUAL; // 년

SELECT ROUND(SYSDATE, 'Q'), TRUNK(SYSDATE, 'Q') FROM DUAL; // 분기

SELECT ROUND(SYSDATE, 'MONTH'), TRUNK(SYSDATE, 'MONTH') FROM DUAL; // 월

SELECT ROUND(SYSDATE, 'W'), TRUNK(SYSDATE, 'W') FROM DUAL; // 주

SELECT ROUND(SYSDATE, 'DAY'), TRUNK(SYSDATE, 'DAY') FROM DUAL; // 일

SELECT ROUND(SYSDATE, 'HH'), TRUNK(SYSDATE, 'HH') FROM DUAL; // 시

SELECT ROUND(SYSDATE, 'MI'), TRUNK(SYSDATE, 'MI') FROM DUAL; // 분

ROUND(날짜), TRUNK(날짜) // 일

SELECT TRUNK(SYSDATE) FROM DUAL; // 현재 날짜(시간 제외)

 

27. 형식 변환 함수

 

TO_CHAR() // 숫자, 날짜를 문자로 변환

 

TO_CHAR(NUMBER) // NUMBER 형식을 문자열(VARCHAR2)로 변환

TO_CHAR(NUMBER, 형식)

TO_CHAR(1234567890, '$099,999,999.99') // $012,345,678.90

9, 0 // 숫자, 빈 자리를 채우는 문자

왼쪽 변환 대상을 오른쪽 형식에 맞추어 변환한다. 변환 대상의 자릿수와 형식의 자릿수가 같거나 변환 대상의 자릿수보다 형식의 자릿수가 더 커야한다. 형식의 자릿수가 더 큰 경우 형식 앞에 0이 있으면 나머지 자리는 0으로 변환되고 형식 앞에 0이 없으면 나머지 자리가 공백으로 변환된다.

소수점에서 0과 9의 의미는 같다. 변환 대상의 소수점 자릿수가 형식의 소수점 자릿수 보다 더 큰 경우 형식에서 0과 9는 숫자의 의미를 가지며 형식의 소수점 자릿수에 맞추어 반올림 되어 변환된다. 변환 대상의 소수점 자릿수가 형식의 소수점 자릿수 보다 더 작은 경우 형식에서 0과 9는 빈 자리를 채우는 문자의 의미를 가지며 나머지 자리는 0으로 변환된다.

 

TO_CHAR(DATETIME) // DATE 형식을 문자열(VARCHAR2)로 변환

TO_CHAR(DATETIME, 형식)

TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:MI:SS')

 

TO_DATE(문자열) // 문자열을 날짜 형식으로 변환하는 함수 

TO_DATE(문자열, 형식) // 문자열이 NLS_DATE_FORMAT이 아닌 경우 형식 설정

TO_DATE(SYSDATE, 'YYYY-MM-DD HH:MI:SS')

TO_TIMESTAMP(문자열) // 문자열을 날짜 형식으로 변환하는 함수 

TO_TIMESTAMP(문자열, 형식) // 문자열이 NLS_TIMESTAMP_FORMAT이 아닌 경우 형식 설정

TO_TIMESTAMP(SYSTIMESTAMP, 'YYYY-MM-DD HH:MI:SS')

 

TO_NUMBER(문자열) // 문자열을 숫자 형식으로 변환하는 함수 

 

28. NULL 관련 함수와 DECODE 함수

 

NVL(입력값, 대체값) // 입력값이 NULL일 경우에 대체값을 제공하는 함수

SELECT NVL(AGE, 0) FROM MEMBERS;

 

NVL2(입력값, NOT NULL 대체값, NULL 대체값) // 입력값이 NOT NULL, NULL일 경우에 대체값을 제공하는 함수

SELECT NVL2(AGE, 100/AGE, 0) FROM MEMBERS;

 

NULLIF(입력값1, 입력값2) // 두 값이 같은 경우 NULL, 그렇지 않은 경우 첫 번째 값을 반환하는 함수

SELECT NULLIF(AGE, 19) FROM MEMBERS;

 

COALESCE(COLUMN_NAME1, COLUMN_NAME2, ..., COLUMN_NAMEN) // NULL이 아닌 최초의 컬럼값을 출력

 

DECODE(입력값, 비교값1, 출력값1, 비교값2, 출력값2, ..., 비교값이 아닌 경우 출력값) // 조건에 따른 값 선택하기 

SELECT DECODE(SUBSTR(PHONE, 1, 3),

'011', 'SK',

'016', 'KT',

'기타') FROM MEMBERS;

 

29. SELECT 구절과 정렬(ORDER BY)

 

SELECT문의 구절

SELECT - FROM - WHERE - GROUP BY - HAVING - ORDER BY

ORDER BY에서 ,로 구분하여 정렬 기준을 추가할 수 있다.

 

30. 집계 함수와 GROUP BY

 

SELECT COUNT(COLUMN_NAME) FROM TABLE_NAME // NULL 제외 개수

SELECT COUNT(*) FROM TABLE_NAME // NULL 포함 개수

 

SELECT COLUMN1, COUNT(*) FROM TABLE GROUP BY ROLLUP(COLUMN1) // GROUP BY COLUMN1 합계 + 총 합계

 

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY ROLLUP(COLUMN1, COLUMN2) // GROUP BY COLUMN1, COLUMN2 합계 + GROUP BY COLUMN1 합계 + 총 합계

 

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY ROLLUP((COLUMN1, COLUMN2)) // GROUP BY COLUMN1, COLUMN2 합계 + 총 합계

 

SELECT COLUMN1, COUNT(*) FROM TABLE GROUP BY CUBE(COLUMN) // GROUP BY COLUMN1 합계 + 총 합계

 

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY CUBE(COLUMN1, COLUMN2);

SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY CUBE(COLUMN2, COLUMN1);

(ROLLUP 함수와 달리 컬럼의 순서가 결과에 영향을 주지 않는다.)

// SELECT COLUMN1, COLUMN2, COUNT(*) FROM TABLE GROUP BY COLUMN1, COLUMN2

UNION ALL

SELECT COLUMN1, NULL, COUNT(*) FROM TABLE GROUP BY COLUMN1

UNION ALL

SELECT NULL, COLUMN2, COUNT(*) FROM TABLE GROUP BY COLUMN2

UNION ALL

SELECT NULL, NULL, COUNT(*) FROM TABLE

ORDER BY 1, 2;

 

SELECT NTILE(N) OVER(ORDER BY COLUMN1) FROM TABLE1 // 대상 데이터를 N만큼 분할하여 N개의 숫자 부여, 대상 데이터가 N개 초과 시 1부터 중복 부여

 

누적 합계

 

실행순서

FROM - CONNECT BY - WHERE - GROUP BY - HAVING - SELECT - ORDER BY

뒤에서 지은 별칭은 앞에서 쓸 수 없다.(SELECT절에서 지정한 ALIAS를 GROUP BY절에서 사용할 수 없다.)

 

31. HAVING 절

 

32. ROW_NUMBER(), RANK(), DENSE_RANK()

 

ROWNUM // WHERE 절에서 생성되며 ORDER BY 사용 시 순서가 바뀐다.

 

ROW_NUMBER() // 정렬 이후 ROWNUM을 붙일 때 사용

SELECT ROW_NUMBER() OVER(ORDER BY HIT) FROM NOTICE; // HIT을 기준으로 정렬하고 ROWNUM을 붙인다.

 

SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY REGDATE DESC) NUM, NOTICE.* FROM NOTICE)

WHERE NUM BETWEEN 6 AND 10;

=

SELECT * FROM(SELECT ROWNUM NUM, N.* FROM (SELECT * FROM NOTICE ORDER BY REGDATE DESC) N)

WHERE NUM BETWEEN 6 AND 10;

 

SELECT ROW_NUMBER() OVER(PARTITION BY WRITER_ID ORDER BY HIT) FROM NOTICE; // WRITER_ID를 기준으로 그룹화(이때 WRITER_ID를 기준으로 오름차순 정렬)한 후 HIT을 기준으로 정렬하고 ROWNUM을 붙인다.

 

SELECT RANK() OVER(ORDER BY HIT) FROM NOTICE; // HIT을 기준으로 정렬하고 순위를 매긴다.(공동 순위가 있으면 다음 순위 생략)

SELECT DENSE_RANK() OVER(ORDER BY HIT) FROM NOTICE; // HIT을 기준으로 정렬하고 순위를 매긴다.(공동 순위가 있어도 다음 순위 인정)

SELECT DENSE_RANK() OVER(PARTITION BY WRITER_ID ORDER BY HIT) FROM NOTICE; // WRITER_ID를 기준으로 그룹화(이때 WRITER_ID를 기준으로 오름차순 정렬)한 후 HIT을 기준으로 정렬하고 순위를 매긴다.

 

33. 부조회(서브쿼리)

 

수학 연산에서 소괄호를 사용하여 연산의 순서를 바꾸듯이 먼저 실행해서 결과를 남겨야 하는 경우 소괄호를 사용하여 나타낸다.

 

스칼라 서브 쿼리(Scalar Subquery) : 한 개의 레코드 당 한 개의 값을 반환 하는 쿼리

인라인 뷰(Inline View) : FROM절에 사용하는 서브 쿼리

중첩 서브 쿼리(Nested Subquery) : WHERE절에 사용하는 서브 쿼리

 

WITH절 // 서브 쿼리에 ALIAS 부여

WITH SQ AS {

    서브 쿼리

}

SELECT * FROM SQ

 

두 번 이상 사용되는 WITH절은 결과값이 temp 영역에 저장되어 디스크 I/O 발생(서브 쿼리의 실행 비용이 큰 경우에만 WITH절을 사용하는 것이 성능상 유리)

Oracle 12.2버전부터는 PGA영역에 저장 후 용량이 부족할 경우에만 temp 영역 사용

 

34. INNER 조인

 

서로 관계가 있는 레코드들은 INNER

서로 관계가 없는 레코드들은 OUTER

INNER JOIN: 참조키를 기준으로 일치하는 행만 조인(관계가 있는 레코드들만 합치는 조인,) OUTER 제외 후 자식 레코드 수 많큼 부모 레코드 복제

 

35. LEFT/RIGTH/FULL OUTER 조인

 

OUTER JOIN: 참조키를 기준으로 일치하지 않는 행도 포함시키는 조인, INNER JOIN에서 OUTER에 해당 하는 레코드 추가, 왼쪽 테이블의 OUTER가 추가되면 LEFT OUTER JOIN, 오른쪽 테이블의 OUTER가 추가되면 RIGHT OUTER JOIN, 왼쪽 테이블의 OUTER와 오른쪽 테이블의 OUTER가 모두 추가되면 FULL OUTER JOIN, OUTER가 추가되지 않는 부분의 테이블 내용은 NULL값이 된다.

 

SELECT * FROM TABLE1 T1 LEFT OUTER JOIN TABLE2 T2 PARTITION BY(T1.COLUMN1) ON T1.ID = T2.ID // T1.COLUMN1으로 GROUP 후 조인

 

36. OUTER JOIN을 이용한 게시글 목록 조회

 

37. SELF JOIN

 

한 테이블의 데이터가 서로 포함 관계를 가지는 경우 사용

SELECT M.*, B.NAME BOSS_NAME FROM MEMBER M LEFT OUTER JOIN MEMBER B ON M.BOSS_ID = B.ID 

 

38. 오라클 OLD JOIN

 

ANSI INNER JOIN

SELECT N.ID, N.TITLE, M.NAME FROM MEMBER M INNER JOIN NOTICE N ON M.ID = N.WRITER_ID

ORACLE INNER JOIN

SELECT N.ID, N.TITLE, M.NAME FROM MEMBER M, NOTICE N WHERE M.ID = N.WRITER_ID

 

ANSI OUTER JOIN

SELECT N.*, M.NAME WRITER_NAME FROM NOTICE N LEFT OUTER JOIN MEMBER M ON M.ID = N.WRITER_ID

Oracle OUTER JOIN

SELECT N.*, M.NAME WRITER_NAME FROM NOTICE N, MEMBER M WHERE M.ID(+) = N.WRITER_ID

 

Oracle SQL의 경우 FULL OUTER JOIN은 지원하지 않음

 

ANSI CROSS JOIN

SELECT N.*, M.NAME WRITER_NAME FROM NOTICE N CROSS JOIN MEMBER M

Oracle CROSS JOIN

SELECT N.*, M.NAME WRITER_NAME FROM NOTICE N, MEMBER M

 

NATURAL JOIN

SELECT * FROM TABLE1 NATURAL JOIN TABLE2 USING(COLUMN1, COLUMN2)

// 두 테이블의 컬럼명과 데이터 타입이 같은 컬럼을 기준으로 JOIN, USING절을 사용하여 기준 컬럼 선택 가능

이때 기준 컬럼 앞에는 테이블명을 명시할 수 없음

 

39. 유니온(UNION)

 

// ROW를 기준으로 합치는 작업

UNION // 합집합(같은 ROW는 하나만 남김)

MINUS // 차집합

INTERSECT //교집합

UNIONALL // 합집합 + 교집합(같은 ROW도 전부 남김)

 

40. View의 의미와 생성 방법

 

VIEW 생성

CREATE VIEW VIEW1 AS ~

 

VIEW 조회

SELECT * FROM VIEW1

 

VIEW 삭제

DROP VIEW VIEW1

 

41. 데이터 딕셔너리

 

SELECT * FROM DICT; // 데이터 딕셔너리 조회

DBA_, USER_, ALL_ // 권한

SELECT * FROM USER_TABLES; // USER 권한의 TABLE

SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'TABLE1'; // USER 권한의 TABLE1의 COLUMN

SELECT * FROM USER_CONSTRAINT WHERE TABLE_NAME = 'TABLE1';

 

42. 도메인 제약조건

 

도메인 // 유효한 값의 범위

도메인 제약조건 // COLUMN에 도메인이 아닌 값이 올 수 없도록 하는 제약조건

NOT NULL 제약조건, DEFAULT 제약조건, CHECK 제약조건

 

43. 체크 제약조건

 

CHECK(PHONE LIKE '010-%-____')

 

44. 정규식을 이용한 체크 제약조건

 

CHECK(REGEXP_LIKE(PHONE, '^010-\d{3, 4}-\d{4}$'))

 

ALTER TABLE DROP CONSTRAINT CONSTRAINT1;

 

45. Entity 제약조건(Primary Key, Unique)

 

엔티티 제약조건 // 테이블에 중복된 ROW가 없도록 하는 제약조건

PRIMARY KEY(NOT NULL, 중복X), UNIQUE(NULL 허용, 중복 X), UNIQUE INDEX 생성

CONSTRAINT PK_NAME PRIMARY KEY(PK_COLUMN)

CONSTRAINT UNIQUE_NAME UNIQUE(UNIQUE_COLUMN)

 

FK 설정 시 부모 테이블이 생성되어 있어야 하며 참조 컬럼은 PK나 UK로 설정되어 있어야 한다. 또한 FK와 참조 컬럼은 데이터 타입과 내용이 일치해야 함

CONSTRAINT FK_NAME FOREIGN KEY(FK_COLUMN) REFERENCES 부모 테이블(참조 컬럼)

 

46. 시퀀스(Sequence)

 

SEQUENCE // 일련번호

CREATE SEQUENCE NOTICE_ID_SEQ(시퀀스 명) INCREMENT 1(1씩 증가, 생략하면 1씩 증가) START WITH 1(1부터 시작, 생략하면 1부터 시작);

INSERT INTO NOTICE(ID, TITLE, WRITER_ID) VALUES(NOTICE_ID_SEQ.NEXTVAL, ' ', ' ')

SEQUENCE값을 자동으로 증가시켜 입력하기 위해서 열 시퀀스 사용


SYNONYM

 

CREATE SYNONYM TABLE1 FOR A.TABLE1

 

트리거

CREATE OR REPLACE TRIGGER TRIGGER1

AFTER INSERT OR UPDATE OR DELETE ON TABLE1

FOR EACH ROW

BEGIN

    IF INSERTING THEN

        INSERT INTO TABLE2 VALUES(:NEW.COLUMN1, :NEW.COLUMN2, SYSDATE)

    END IF;

 

    IF UPDATING THEN

        ~

    END IF; // :OLD를 사용하여 변경 전 데이터 사용 가능

 

    IF DELETING THEN

        ~

    END IF;

END;

 

데이터 복구

SHOW PARAMETER UNDO_RETENTION // UNDO_RETENTION 반환(초 단위)

 

INSERT INTO TABLE1

SELECT * FROM TABLE1

AS OF TIMESTAMP(SYSTIMESTAMP - INTERVAL '15' MINITE)

WHERE ~

 

정규화

제1 정규형

원자성 // 모든 속성은 반드시 하나의 값만 가져야 한다.(다중 값, 반복 그룹X)

 

제2 정규형

부분 종속 // 모든 속성은 반드시 모든 기본키에 종속되어야 한다.(기본키 일부에만 종속되어서는 안됨)

 

제3 정규형

이행 종속 // 기본키가 아닌 모든 속성간에는 서로 종속될 수 없다.

 

반정규화

1. 테이블 반정규화

테이블 병합 // 비지니스 로직 상 JOIN 되는 경우가 많아 통합하는 것이 성능 측면에서 유리할 경우 고려

1) 1:1 관계 테이블 병합

2) 1:M 관계 테이블 병합

3) 슈퍼 서브 타입 테이블 병합

 

테이블 분할

1) 수직 분할 // 컬럼 단위로 테이블을 1:1 분리

2) 수평 분할 // row 단위로 테이블 분리

 

테이블 추가

1) 중복 테이블 추가 // 타 업무 또는 타 서버에 있는 테이블과 동일한 구조의 테이블 추가, 원격 JOIN 방지

2) 통계 테이블 추가 // 통계값을 미리 계산해서 저장하는 테이블 추가

3) 이력 테이블 추가 // 마스터 테이블에 존재하는 row를 트랜잭션 발생 시점에 따라 복사해두는 테이블 추가

4) 부분 테이블 추가 // 자주 조회되는 컬럼들만 별도로 모아놓은 테이블 추가

 

2. 컬럼 반정규화

중복 컬럼 추가 // JOIN 프로세스를 줄이기 위해 중복 컬럼 추가, SELECT 비용은 감소하나 UPDATE 비용은 증가

파생 컬럼 추가 // 계산을 통해 얻어지는 결과값을 테이블에 컬럼으로 저장

이력 테이블 컬럼 추가 // 이력 테이블에 기능성 컬럼 추가(최신 여부, 시작일/종료일 등)

 

3. 관계 반정규화

중복관계 추가 // 데이터 처리를 위해 여러 경로를 거쳐야할 경우 관계를 중복시킴으로써 성능 개선

'Web Programming' 카테고리의 다른 글

Unable to compile class for JSP  (0) 2021.11.14
테스트  (0) 2021.06.26
배포  (0) 2021.06.21
CGI를 이용하여 아파치(Apache)와 파이썬(Python) 연동하기  (0) 2021.01.15