9. 조건 연산자#
이장에서는 SQL 문에 사용되는 조건 연산자들에 대해서 자세히 설명한다.
SQL 조건의 개요#
SQL 조건은 한 개 이상의 논리 연산자와 수식으로 구성된다. 조건의 반환 값은 TRUE, FALSE, 또는 UNKOWN 셋 중의 하나이다.
조건은 SELECT 구문의 다음 절에 사용될 수 있다:
-
WHERE
-
START WITH
-
CONNECT BY
-
HAVING
또한, 조건은 DELETE 또는 UPDATE 구문의 WHERE 절에도 사용될 수 있다.
이 절은 다양한 종류의 조건에 대해서 상세히 설명한다.
논리 조건#
다음의 논리 조건들이 Altibase에서 지원된다. 다음 표는 각각에 대한 간략한 설명을 보여준다.
논리 연산자 | 설명 |
---|---|
논리곱 (AND) | 입력 조건들의 논리곱 결과를 돌려준다. 두 조건이 모두 TRUE이면 TRUE를 반환한다. 둘 중 하나라도 FALSE이면 FALSE를 반환한다. |
부정 (NOT) | 입력된 값의 반대 결과를 돌려준다. |
논리합 (OR) | 입력 조건들의 논리합 결과를 돌려준다. 두 조건이 모두 FALSE이면 FALSE를 반환한다. 둘 중 하나라도 TRUE이면 TRUE를 반환한다. |
비교 조건#
비교 조건은 단순 비교와 그룹 비교로 분류될 수 있다.
단순 비교 조건은 한 수식이 한 수식과 비교되는 것이다.
그룹 비교 조건은 한 수식이 여러 수식들과 비교되거나 부질의에 의해 반환되는 다수의 행과 비교되는 것이다.
그 외의 조건#
Altibase에서 지원되는 다른 조건들이 다음 표에 간략히 설명되어 있다.
조건 타입 | 설명 |
---|---|
BETWEEN 조건 | BETWEEN 조건은 비교 조건의 일종으로 어떤 값이 일정 범위 내에 속하는지 검사한다. |
EXISTS 조건 | EXISTS 조건은 부질의가 적어도 하나 이상의 행을 반환하는지 검사한다. |
IN 조건 | IN 조건은 어떤 값이 리스트 또는 부질의가 반환한 결과 중의 하나 이상의 값과 같은지 검사한다. NOT IN 조건은 어떤 값이 리스트 또는 부질의가 반환한 결과 중의 모든 값과 같지 않은지를 검사한다. |
INLIST 조건 | INLIST 조건은 어떤 값이 주어진 목록 안에 있는지 검사한다. |
IS NULL 조건 | IS NULL 조건은 어떤 값이 널인지 검사한다. |
LIKE 조건 | LIKE 조건은 패턴 일치 검사 조건으로 문자열이 주어진 패턴을 포함하는지 검사한다. |
REGEXP_LIKE 조건 | REGEXP_LIKE 조건은 문자열이 주어진 정규 표현식을 포함하는지 검사한다. |
UNIQUE 조건 | UNIQUE 조건은 부질의가 오직 하나의 행을 반환하는지 검사한다. |
논리 연산자#
AND#
구문#
condition1 AND condition2
설명#
AND는 condition1과 condition2를 논리곱 연산한 결과를 돌려준다.
논리곱 연산의 결과는 다음과 같다.
Condition1 (우) Condition2(하) |
TRUE | FALSE | UNKNOWN |
---|---|---|---|
TRUE | TRUE | FALSE | UNKNOWN |
FALSE | FALSE | FALSE | FALSE |
UNKNOWN | UNKNOWN | FALSE | UNKNOWN |
예제#
<질의> 엔지니어이면서 급여가 2000 이상인 직원의 이름, 급여, 입사일을 출력하라.
SELECT e_firstname
, e_lastname
, salary
, join_date
FROM employees
WHERE emp_job = 'engineer'
AND salary >= 2000;
E_FIRSTNAME E_LASTNAME SALARY JOIN_DATE
--------------------------------------------------------------------------
Ken Kobain 2000 11-JAN-2010
1 row selected.
NOT#
구문#
NOT condition
설명#
NOT은 입력 condition의 반대 결과를 돌려준다.
Condition | TRUE | FALSE | UNKNOWN |
---|---|---|---|
NOT 결과 | FALSE | TRUE | UNKNOWN |
예제#
<질의> 1980년 이전에 태어난 사원을 제외한 사원들의 이름, 부서, 생일을 출력하라.
SELECT e_lastname
, e_firstname
, dno
, birth
FROM employees
WHERE NOT birth < BYTE'800101';
E_LASTNAME E_FIRSTNAME DNO BIRTH
---------------------------------------------------------------------
Foster Aaron 3001 820730
Fleischer Gottlieb 4002 840417
Wang Xiong 4001 810726
Hammond Sandra 4002 810211
Jones Mitch 1002 801102
Davenport Jason 1003 901212
6 rows selected.
OR#
구문#
condition1 OR condition2
설명#
OR은 condition1과 condition2를 논리합 연산한 결과를 돌려준다.
논리합 연산의 결과는 다음과 같다.
Condition1 (우) Condition2(하) |
TRUE | FALSE | UNKNOWN |
---|---|---|---|
TRUE | TRUE | TRUE | TRUE |
FALSE | TRUE | FALSE | UNKNOWN |
UNKNOWN | TRUE | UNKNOWN | UNKNOWN |
예제#
<질의> 재고 수량이 20000 이상이거나 단가가 100000원 이상인 상품의 데이터를 출력하라.
SELECT *
FROM GOODS
WHERE STOCK > 20000
OR PRICE >= 100000;
GNO GNAME GOODS_LOCATION STOCK PRICE
---------------------------------------------------------------------------------
C111100001 IT-U950 FA0001 35000 7820.55
D111100008 TM-U200 AC0006 61000 10000
E111100004 M-190G CE0001 88000 5638.76
E111100012 M-U420 CE0003 43200 3566.78
F111100001 AU-100 AC0010 10000 100000
5 rows selected.
비교조건#
비교조건은 한 수식이 한 개 또는 여러 개의 수식과 비교되는지에 따라서 크게 단순 비교조건과 그룹 비교조건으로 분류될 수 있다.
단순 비교 조건#
구문#
simple_comparison_condition ::=#
설명#
단순 비교 조건은 명시된 연산자를 기준으로 양쪽의 수식을 비교하여 TRUE, FALSE 또는 UNKNOWN을 반환한다.
단순 비교 조건은 두 식의 크기를 비교하는 것과 두 식이 동일한지를 판단하는 것으로 분류될 수 있다.
두 개 이상의 수식이 연산자의 양쪽에 존재할 때 (위의 다이어그램에서 아래쪽에 해당), 오직 동등 비교만 수행될 수 있다. 즉, 크기 비교는 불가능하다.
또한, 연산자 왼쪽의 수식 개수는 오른쪽 수식의 개수와 동일해야 한다. 이 규칙은 수식이 부질의(subquery) 형태로 올 경우 SELECT 목록의 개수에도 적용된다.
게다가, 부질의가 단순 비교에 사용될 때 이는 오직 한 레코드만 반환해야 한다.
예제#
<질의> 재고금액이 1억원 이상인 상품의 품명, 보관수량, 원가, 재고금액을 출력하라. (재고금액은 보관수량 * 원가이다.)
SELECT gname
, stock
, price
, stock*price value_of_inv
FROM goods
WHERE stock*price > 100000000;
GNAME STOCK PRICE VALUE_OF_INV
------------------------------------------------
IT-U950 35000 7820.55 273719250
TM-T88 10000 72000 720000000
TM-U950 8000 96200 769600000
.
.
.
11 rows selected.
그룹 비교 조건#
구문#
group_comparison_condition ::=#
설명#
그룹 비교 조건에서는 왼쪽의 수식이 오른쪽의 각 수식 또는 부질의 결과와 비교된다. 다수의 행을 반환하는 부질의도 허용된다.
연산자 왼쪽에 두 개 이상의 수식이 올 경우, 오직 동등 비교만 수행될 수 있고, 크기 비교는 불가능하다. 또한, 오른쪽 수식에는 그룹으로 묶기 위해서 괄호를 사용해야 한다. 각 그룹내의 요소들의 개수 또는 부질의에 의해 반환되는 칼럼의 개수는 왼쪽 수식의 개수와 동일해야 한다.
ANY / SOME#
ANY와 SOME 키워드는 같은 의미를 가지고 있다. 이 키워드를 포함하는 그룹 비교 조건은 왼쪽 수식과 오른쪽 수식들 또는 부질의 결과 중 적어도 하나의 수식과 비교한 결과가 TRUE이면, TRUE를 반환한다.
ALL#
ALL 키워드를 포함하는 그룹 비교 조건은 왼쪽의 수식과 오른쪽의 수식들 또는 부질의 결과 모두를 비교해서 모든 경우에 대해서 TRUE일때, TRUE를 반환한다.
예제#
<질의> 성이 "B"로 시작되는 사원이 받은 모든 주문에 대한 정보를 출력하라.
SELECT ono
, order_date
, processing
FROM orders
WHERE eno = ANY (SELECT eno
FROM employees
WHERE e_lastname LIKE 'B%');
ONO ORDER_DATE PROCESSING
--------------------------------------------------
12300003 29-DEC-2011 P
12300004 30-DEC-2011 P
12300006 30-DEC-2011 P
12300008 30-DEC-2011 P
12300009 30-DEC-2011 P
12300011 30-DEC-2011 P
12300013 30-DEC-2011 P
12310001 31-DEC-2011 O
12310003 31-DEC-2011 O
12310005 31-DEC-2011 O
12310006 31-DEC-2011 O
12310010 31-DEC-2011 O
12 rows selected.
그 외의 조건#
BETWEEN#
구문#
between_condition ::=#
설명#
BEETWEEN 비교는 어떤 값이 주어진 범위에 속하는지를 체크하기 위해 사용된다.
'column1 between x1 and x2'는 'column1 >= x1 and column1 <= x2'와 논리적으로 동일하다.
예제#
<질의> 재고금액이 100만원 이상 1000만원 이하인 상품의 품명, 보관수량, 원가, 재고금액을 출력하라. (재고금액은 보관수량 * 원가이다.)
SELECT gname
, stock
, price
, stock*price value_of_inv
FROM goods
WHERE stock*price BETWEEN 1000000 AND 10000000;
GNAME STOCK PRICE VALUE_OF_INV
------------------------------------------------
IM-310 100 98000 9800000
.
.
.
M-T500 5000 1000.54 5002700
7 rows selected.
EXISTS#
구문#
exists_condition ::=#
설명#
EXIST는 부질의의 결과가 적어도 하나 이상 존재하는지 검사한다. 적어도 하나의 행이 존재하면 EXIST는 TRUE를 반환한다.
예제#
<질의> 적어도 두 종류 이상의 상품을 주문한 고객의 고객번호를 출력하라. (먼저 부질의에서는 주문 테이블에서 같은 고객번호이지만 다른 상품을 주문한 행의 쌍을 모두 찾는다. 즉, 한 고객이 한 개 이상의 다른 상품을 주문한 것을 의미한다. 만약, 그러한 행의 쌍이 존재하면, EXISTS는 TRUE를 반환하고, 그 고객번호는 출력된다.)
SELECT DISTINCT cno
FROM orders a
WHERE EXISTS (SELECT *
FROM orders b
WHERE a.cno = b.cno
AND NOT(a.gno = b.gno));
CNO
------------------
19
15
14
11
6
5
3
2
1
9 rows selected.
<질의> 모든 상품을 주문한 고객의 이름을 출력하라. 맨 아래쪽에 위치하는 가장 안쪽 질의는 주문 테이블에서 고객이 주문한 상품들을 찾는다. 가운데 질의는 그 고객에 의해 주문되지 않은 상품을 찾는다. 만약, 그 고객에 의해 주문되지 않은 상품이 없으면 그 고객의 이름이 출력될 것이다.)
SELECT customers.c_lastname
FROM customers
WHERE NOT EXISTS (SELECT *
FROM goods
WHERE NOT EXISTS (SELECT *
FROM orders
WHERE orders.cno = customers.cno
AND orders.gno = goods.gno));
CNAME
------------------------
No rows selected.
IN#
구문#
in_condition ::=#
설명#
IN 조건은 '= ANY' 조건을 사용한 그룹 비교와 동일하다. 이런 종류의 조건은 왼쪽의 수식이 오른쪽 수식들 중 어느 하나와 일치하면 TRUE를 반환한다.
NOT IN 조건은 '!= ALL' 조건을 사용한 그룹 비교와 동일하다. 이런 종류의 조건은 오른쪽 수식들 중 어느 하나도 왼쪽 수식과 일치하지 않을 때 TRUE를 반환한다.
예제#
<질의> 응용프로그램 개발 팀 또는 마케팅 팀에서 일하고 있는 사원의 이름, 업무, 전화번호, 입사일을 출력하라.
SELECT e_firstname
, e_lastname
, emp_job
, emp_tel
FROM employees
WHERE dno IN (1003, 4001);
E_FIRSTNAME E_LASTNAME EMP_JOB EMP_TEL
-------------------------------------------------------------------------
Elizabeth Bae programmer 0167452000
Zhen Liu webmaster 0114553206
.
.
.
7 rows selected.
위 SQL문의 WHERE 절은 다음과 같은 의미를 지닌다:
WHERE DNO = 1003 or DNO = 4001
<질의> 상품 C111100001을 주문한 고객의 이름을 출력하라.
SELECT DISTINCT customers.c_lastname
, customers.c_firstname
FROM customers
WHERE customers.cno IN
(SELECT orders.cno
FROM orders
WHERE orders.gno = 'C111100001');
C_LASTNAME C_FIRSTNAME
-----------------------------------------------
Martin Pierre
Fedorov Fyodor
Dureault Phil
Sanchez Estevan
4 rows selected.
INLIST#
구문#
inlist_condition ::=#
설명#
INLIST는 comma_separated_values 내 각각의 값 중 어느 하나가 expr과 일치하면 TRUE를 반환한다.
NOT INLIST는 comma_separated_values 내 각각의 값 중 어느 것도 expr과 일치하지 않으면 TRUE를 반환한다.
comma_separated_values 내의 각 값은 ASCII 문자로만 이루어진 문자열이어야 한다.
예제#
SELECT dno
, e_firstname
, e_lastname
FROM employees
WHERE INLIST (dno, '1003, 4001' );
DNO E_FIRSTNAME E_LASTNAME
------------------------------------------------------------
1003 Elizabeth Bae
1003 Zhen Liu
1003 Yuu Miura
1003 Jason Davenport
4001 Xiong Wang
4001 Curtis Diaz
4001 John Huxley
7 rows selected.
IS NULL#
구문#
isnull_condition ::=#
설명#
IS NULL 조건은 표현식(expression)이 널(NULL) 인지 아닌지 검사하기 위해 사용된다.
예제#
<질의> 생일이 입력 되지 않은 직원의 사원번호, 이름, 업무를 출력하라.
SELECT eno
, e_firstname
, e_lastname
, emp_job
FROM employees
WHERE salary IS NULL;
ENO E_FIRSTNAME E_LASTNAME EMP_JOB
---------------------------------------------------------------------------
1 Chan-seung Moon CEO
8 Xiong Wang manager
20 William Blake sales rep
3 rows selected.
LIKE#
구문#
like_condition ::=#
설명#
LIKE는 패턴 일치 검사 조건으로써, 어떤 문자열이 주어진 패턴(문자열)을 포함하는지를 검사한다. LIKE 조건은 퍼센트("%")와 밑줄("_") 문자를 와일드카드 문자로 사용한다. "%"는 문자열을 나타내고, "_"는 한 문자를 나타낸다.
그러나 "%" 또는 "_"를 와일드카드 문자가 아닌 실제 문자 "%" 또는 "_"로 사용하려는 경우에는 이스케이프(ESCAPE) 문자를 사용하면 된다. ESCAPE 키워드 다음에 이스케이프 문자로 사용할 문자를 명시하고, 패턴 문자열에서 "%" 또는 "_" 앞에 이 이스케이프 문자를 기술하면, "%" 또는 "_"가 와일드카드 문자로 인식되지 않는다.
패턴 문자열의 길이는 최대 4000 바이트로 제한된다.
예제#
<질의> 성이 "D"로 시작되는 직원들의 사원번호, 이름, 부서번호, 전화번호를 출력하라.
SELECT eno
, e_lastname
, e_firstname
, dno
, emp_tel
FROM employees
WHERE e_lastname LIKE 'D%';
ENO E_LASTNAME E_FIRSTNAME DNO EMP_TEL
---------------------------------------------------------------------------------
2 Davenport Susan 0113654540
9 Diaz Curtis 4001 0165293668
15 Davenport Jason 1003 0119556884
3 rows selected.
<질의> 부서 이름에 밑줄("_")이 포함된 모든 부서에 대한 정보를 출력하라.
INSERT INTO departments VALUES(5002, 'USA_HQ', 'Palo Alto', 100);
SELECT *
FROM departments
WHERE dname LIKE '%\_%' ESCAPE '\';
DNO DNAME DEP_LOCATION MGR_NO
---------------------------------------------------------------
5002 USA_HQ Palo Alto 100
1 row selected.
위 예제에서 백슬래시 ("\")가 escape 문자로 정의되었다. 이 escape 문자가 밑줄("_") 앞에 있으므로 밑줄이 와일드카드로 다뤄지지 않는다.
<질의> 이름에 "h"가 들어간 모든 사원의 이름을 출력하라.
SELECT e_firstname
FROM employees
WHERE e_firstname LIKE '%h%';
E_FIRSTNAME
------------------------
Chan-seung
Farhad
Elizabeth
Zhen
Mitch
Takahiro
John
7 rows selected.
REGEXP_LIKE#
구문#
regexp_like_condition ::=#
설명#
REGEXP_LIKE는 LIKE 검사 조건과 유사하다. LIKE가 단순한 패턴 일치 검사라면, REGEXP_LIKE는 정규 표현식 일치 검사를 수행한다. Altibase는 POSIX Basic Regular Expression (BRE)을 지원한다. 정규 표현식에 대한 자세한 설명은 "A.부록: 정규 표현식"을 참고하라.
source_expr에는 검색 대상이 되는 칼럼이나 문자 표현식이 올 수 있으며, 일반적으로 CHAR, VARCHAR 같은 문자 타입의 칼럼이 온다.
pattern_expr에는 검색 패턴을 정규 표현식으로 표현한 값이 올 수 있으며, 일반적으로 문자열이 온다. pattern_expr에는 최대 1024 바이트까지 입력할 수 있다.
예제#
<질의> 이름의 성이 "D"로 시작되는 직원들의 사원번호, 이름, 부서번호, 전화번호를 출력하라.
SELECT eno
, e_lastname
, e_firstname
, dno
, emp_tel
FROM employees
WHERE REGEXP_LIKE(e_lastname, '^D');
ENO E_LASTNAME E_FIRSTNAME DNO EMP_TEL
---------------------------------------------------------------------------------
2 Davenport Susan 0113654540
9 Diaz Curtis 4001 0165293668
15 Davenport Jason 1003 0119556884
3 rows selected.
<질의> 이름의 성이 다섯 개의 문자로 이루어진 직원을 출력하라.
SELECT eno
, e_lastname
, emp_job
FROM employees
WHERE REGEXP_LIKE(TRIM(e_lastname), '^.{5}$');
ENO E_LASTNAME EMP_JOB
--------------------------------------------------
6 Momoi programmer
13 Jones PM
14 Miura PM
20 Blake sales rep
4 rows selected.
UNIQUE#
구문#
unique_condition ::=#
설명#
UNIQUE는 부질의가 오직 하나의 레코드만 반환하는지 검사한다.
예제#
<질의> CEO가 오직 한명이면, 다음의 메시지를 출력하라: "There is only one CEO."
SELECT 'There is only one CEO.' message
FROM DUAL
WHERE UNIQUE (SELECT *
FROM employees
WHERE emp_job = 'CEO');
MESSAGE
--------------------------
There is only one CEO.
1 row selected.
<질의> 고객 테이블에 여성이 한명만 있을 경우 다음의 메시지를 출력하라: 'There is only one female customer.'
SELECT 'There is only one female customer.' message
FROM DUAL
WHERE UNIQUE (SELECT *
FROM customers
WHERE SEX = 'F');
ENAME
------------------------
No rows selected.