포스트

SQLD: 함수, WHERE

함수

함수는 입력 값을 넣어 특정한 기능을 통해 결과 값을 출력해준다.

함수가 어떻게 만들어져 있는지는 알 필요가 없으며, 입력 개수, 출력 개수, 그리고 기능만 알면 된다.

내장형 함수

내장형 함수란 DBNS에 미리 만들어져 있어 사용이 가능한 함수이다.

문자형 함수: UPPER, SUBSTR, TRIM, REPLACE …

숫자형 함수: MOD, ROUND …

날짜형 함수: SYSDATE …

UPPER

1
2
3
SELECT UPPER('abcde123@@') AS UPPER사용

FROM DUAL;  -- dual은 테스트할 때 쓰이는 테이블  

UPPER는 문자열뿐만이 아니라 컬럼도 선택할 수 있다:

1
2
3
SELECT CUST_ID, PASSWD, UPPER(PASSWD) AS 패스워드대문자

FROM TB_CUST

SUBSTR

SUBSTR(문자형 리터럴, 시작위치, 길이) 형식으로 사용한다.

특정 문자형 리터럴의 시작위치부터 길이만큼 잘라서 출력한다.

TRIM

TRIM은 공백을 제거한다.

SELECT TRIM(' 안녕하세요 ')를 하면 ‘안녕하세요’가 출력된다.

REPLACE

REPLACE는 특정 문자를 다른 문자로 변경해준다.

ROUND

ROUND는 반올림한 결과를 출력해준다.

입력 값으로 숫자형 리터럴 2개를 받으며, 첫 수는 실수이며 두번째 수는 소수점의 자리 수이다.

1
2
SELECT ROUND(1.452, 2), ROUND(1.452, 1)
FROM DUAL

결과: 1.42, 1.5

자료형

문자, 숫자, 날짜가 있다. 이들을 변환하는 함수들은 TO_DATE(), TO_CHAR, TO_NUMBER이다.

날짜

SYSDATE는 현재 날짜를 날짜형 데이터로 출력하는 날짜형 함수이다. 날짜의 포맷은 다음과 같다:

YYYY: 연도 4자리
MM: 월 2자리
DD: 일 2자리
HH24: 24시간제 시간 (오후 1시 -> 13시)
HH: 12시간제
MI: 분
SS: 초

1
2
3
4
5
SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') FROM DUAL;

SELECT TO_DATE('20240817', 'YYYY/MM/DD') FROM DUAL; -- 출력값: 2024-08-17 00:00:00
SELECT TO_DATE('2024081701141212', 'YYYY/MM/DD HH24:MI:SS') FROM DUAL; -- 출력값: 2024-08-17 14:12:12

연산을 하기 전에 먼저 형변환이 발생한다. 형 변환의 우선순위는 문자형 < 숫자형 < 날짜형 이다. 즉, 날짜형이 가장 우선순위가 높다.

1
SELECT CUST_NAME + 1000 FROM TB_CUST;

위의 예시와 같이 사칙 연산을 할 때 CUST_NAME은 문자형이고, 1000은 숫자형이면 형을 통일해야 하는데 문자형을 숫자형에 맞춰준다. 즉, TO_NUMBER(CUST_NAME) 이 먼저 발생한다는 것이다.

여기서 발생할 수 있는 문제는, CUST_NAME의 값이 숫자로 변환될 수 있는 형태가 아니라면 INVALID NUMBER이라는 오류가 뜰 수 있다.

NULL

NULL은 정상적인 산술, 비교 연산 등이 불가능하다.

1
SELECT 3 + NULL FROM DUAL; -- (null)

NULL은 아직 정해지지 않은 값이기 때문에 NULL을 산술/비교 연산에 사용하면 결과값으로 NULL이 나온다.

NULL 함수란 NULL값을 대체할 수 있는 함수이다.

NVL(data1, data2)

  • data1에 NULL값이 들어오면 data2를 출력하고, NULL이 아니면 data1을 출력한다.
1
2
3
4
SELECT CUST_ID
    ,PHONE_NO
    ,NVL(PHONE_NO, '연락처 없음') AS NVL적용;
  FROM TB_CUST

image

NVL(PHONE_NO, '연락처 없음') AS NVL적용;은 PHONE_NO가 있으면 이를 NVL적용 컬럼에 사용하고, 없으면 ‘연락처 없음’이라는 문구를 사용하겠다는 말이다.

DECODE(data1, data2, data3, data4 …)

  • data1과 data2가 동일하면 data3를 출력하고, 그렇지 않으면 data4를 출력한다.
1
2
3
4
SELECT CUST_ID
    ,PHONE_NO
    ,DECODE(PHONE_NO, NULL, '연락처 없음', PHONE_NO) AS DECODE적용;
  FROM TB_CUST

image

CASE 문법

SQL판 if-else문이다.

1
2
3
4
5
6
7
8
9
SELECT CUST_ID
    ,CUST_NAME
    ,ACT_POINT
    ,CASE WHEN ACT_POINT <= 1000 THEN '브론즈'
          WHEN ACT_POINT <= 10000 THEN '실버'
          WHEN ACT_POINT <= 100000 THEN '골드'
          ELSE '마스터'
     END AS 등급 
  FROM TB_CUST;

WHERE

SELECT * FROM TB_CUST를 하면 모든 TB_CUST의 모든 행이 출력이 된다.

실무 상황에서는 수만 건의 행이 있을텐데 이렇게 하게 되면 비효율적이기 때문에, WHERE절을 사용하여 원하는 내용만 출력할 수 있다.

1
2
3
SELECT CUST_ID, CUST_NAME, BIRTH_DY
  FROM TB_CUST 
  WHERE MONEY = 10000; 

모든 행을 출력하는 것이 아닌, MONEY가 10000인 곳만 출력하도록 WHERE을 사용하여 만들 수 있다.

비교 조건은 =, > , <= 등을 사용하면 된다.

문제1: TB_PRD 테이블에서 PRD_TYPE이 ‘컴퓨터’인 대상의 모든 컬럼을 출력해주세요.
A:

1
2
3
SELECT * 
FROM TB_PRD 
WHERE PRD_TYPE = '컴퓨터';

문제2: TB_PRD 테이블에서 PRD_AMT가 1,000,000이상인 상품의 모든 컬럼을 출력해주세요. A:

1
2
3
SELECT *
FROM TB_PRD
WHERE PRD_AMT >= 1000000;

논리 조건은 AND, OR으로 추가적인 조건을 준다.

문제1: TB_CUST 테이블에서 CUST_ID가 ‘C0001’이고 PASSWD가 ‘pass111’인 대상의 모든 정보를 출력해주세요. A:

1
2
3
4
SELECT * 
FROM TB_CUST
WHERE CUST_ID = 'C0001' 
AND PASSWD = 'pass111';

문제2: TB_PRD 테이블에서 PRD_TYPE이 ‘컴퓨터’이거나 ‘스마트폰’인 대상의 모든 정보를 출력해주세요.
A:

1
2
3
4
SELECT *
FROM TB_PRD
WHERE PRD_TYPE = '컴퓨터'
OR PRD_TYPE = '스마트폰';

부정 연산은 조건에 NOT 개념이 붙은 것이다. 사용 방식은 != 연산자를 쓰는 것과 조건 앞에 ‘NOT’을 쓰는 방법이 있다.

문제1: TB_PRD 테이블에서 PRD_TYPE이 ‘가전’이 아닌 데이터를 출력해주세요.
A:

1
2
3
4
5
6
7
SELECT *
FROM TB_PRD
WHERE NOT PRD_TYPE = '가전';
--
SELECT *
FROM TB_PRD
WHERE PRD_TYPE != '가전';

NULL 연산은 IS NULL/IS NOT NULL로 출력 가능하다.
NULL은 정상적인 산술 연산이 불가능하기 때문에 ‘=’과 ‘!=’을 사용할 수 없다.

문제1: A: TB_CUST 테이블에서 PHONE_NO가 (null)인 데이터를 출력해주세요.

1
2
3
SELECT *
FROM TB_CUST
WHERE PHONE_NO IS NULL;

SQL 연산자

IN

SQL연산자로는 IN, BETWEEN, LIKE가 있는데, 이중 IN 연산자는 OR연산자의 중복 사용을 간단하게 해주는 연산자이다.

가령, 다음과 같은 상황이 있다고 가정해보자:

Q: TB_PRD 테이블에서 PRD_TYPE이 가전이거나, 욕실용품이거나, 스마트폰인 대상의 모든 정보를 출력해주세요.

IN 연산자를 사용하지 않는다면 다음과 같이 작성을 해야 할 것이다.

1
2
3
4
5
SELECT * 
FROM TB_PRD
WHERE PRD_TYPE = '가전'
OR PRD_TYPE = '욕실용품'
OR PRD_TYPE = '스마트폰';

IN 연산자를 사용하게 되면 아래와 같이 한 줄에 작성할 수 있다.

1
2
3
SELECT * 
FROM TB_PRD
WHERE PRD_TYPE IN('가전', '욕실용품', '스마트폰');

BETWEEN

BETWEEN 연산자는 범위조건 연산이다.

Q: TB_CUST 테이블에서 ACT_POINT가 100 이상이면서 1000 이하인 값을 가진 대상의 모든 정보를 출력해주세요.

1
2
3
4
SELECT * 
FROM TB_CUST
WHERE ACT_POINT >= 100
AND ACT_POINT <= 1000;

위의 문을 BETWEEN을 사용하여 아래와 같이 다시 작성할 수 있다.

1
2
3
SELECT * 
FROM TB_CUST
WHERE ACT_POINT BETWEEN(100 AND 1000);

주의해야 하는 점이, BETWEEN은 무조건 A이상 B이하 조건이다. 즉, >=, <= 라는 것이기 떄문에 A와 B값 또한 범위에 포함된다.

LIKE

LIKE연산은 매칭 연산을 할 수 있다.

매칭 연산 = 특정 키워드를 포함한 항목을 찾는 것

LIKE 연산자는 _ 또는 % 같은 와일드카드를 이용해 매칭 연산을 수행한다.

문제1: TB_PRD 테이블에서 PRD_NAME이 ‘수’로 시작하는 모든 정보를 출력해주세요.
A:

1
2
3
SELECT * 
FROM TB_PRD
WHERE PRD_NAME LIKE '수%'

문제2: TB_PRD 테이블에서 PRD_NAME에 ‘용’이 포함되는 모든 정보를 출력해주세요.
A:

1
2
3
SELECT * 
FROM TB_PRD
WHERE PRD_NAME LIKE '%용%'

문제3: TB_PRD 테이블에서 PRD_NAME이 ‘기’로 끝나는 모든 정보를 출력해주세요.
A:

1
2
3
SELECT * 
FROM TB_PRD
WHERE PRD_NAME LIKE '%기'

%는 0개 이상의 문자를 매칭해준다.
_는 1개의 문자를 매칭해준다.


이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.