BumCode

SQL 2

4장 데이터의 추가, 삭제, 갱신

데이터 : 클라이언트 => 서버


[행 추가하기]

mysql> INSERT INTO 테이블명 VALUES( ....);  

-열 지정해서 행 추가하기

mysql> INSERT INTO 테이블명(열1이름,열2이름) VALUES( , );  

-Defalut를 명시적으로 지정하기

mysql> INSERT INTO 테이블명(a,b) VALUES(1,DEFAULT);  

-암묵적으로 저장: 지정하지 않은 열은 Default 값으로 저장됨

+ NULL이 NO로 제약(NOT NULL)이 걸려있다면 VALUES에 NULL을 저장할 수 없음

[행 삭제하기]

DELETE 열 삭제는 불가함

mysql> DELETE FROM 테이블명 WHERE 조건식;
mysql> DELETE FROM 테이블명;

WHERE생략시 모든 행 삭제

[데이터 갱신]

mysql> UPDATE 테이블명 SET 열1=값1, 열2=값2, ... WHERE 조건식;

WHERE구 생략시 모든 행의 지정한 열이 갱신됨
WHERE 조건에 일치하는 모든 행 갱신

SET 열명 = 값 => 여기서 =는 대입연산자

mysql> UPDATE sample41 SET a='update' WHERE a IS NULL;

-SET구 실행순서
실행순서는 제품마다 달라지는 것에 주의

MySQL> UPDATE sample41 SET no = no+1, a = no; 
순서대로 no에는 no+1 대입, a에는 새로 갱신된 no가 대입
Oracle> UPDATE sample41 SET no = no+1, a = no;
순서에 상관없이 a에는 갱신 이전의 no가 대입

-NULL로 갱신
UPDATE sample41 SET a=NULL;
다만 NOT NULL제약시 불가

*UPDATE는 셀을 갱신하는 명령어

[물리삭제와 논리삭제]

-물리삭제
DELETE 명령을 통해 데이터 삭제

-논리삭제
UPDATE 명령을 통해 삭제플래그 값을 갱신, 실제 데이터는 삭제되지 않고 테이블에 남아있으며, 참조시 삭제플래그가 삭제로 설정된 행을 제외하는 SELECT명령 사용


5장 집계와 서브쿼리


[집계함수]

인수로 집합을 지정
집계 : 복수의 값(집합)에서 하나의 값을 계산하는 것
-COUNT
-SUM
-AVG
-MIN
-MAX

mysql> SELECT * FROM sample51;
+------+------+----------+
| no   | name | quantity |
+------+------+----------+
|    1 | A    |        1 |
|    2 | A    |        2 |
|    3 | B    |       10 |
|    4 | C    |        3 |
| NULL | NULL |     NULL |
+------+------+----------+

[COUNT]

인수로 주어진 집합의 ‘개수’를 반환

mysql> SELECT COUNT(*) FROM sample51;
+----------+
| COUNT(*) |
+----------+
|        5 |
+----------+
sample51의 행의 개수 5

-열을 지정하는 경우

mysql> SELECT COUNT(name) FROM sample51;  

name이 NULL인 행은 제외되고 계산됨

반면 COUNT(*)은 모든 열의 행수를 카운트하기에 NULL값이 무시되지 않음

-DISTINCT : 중복된 값을 제거(다른 집계함수에서도 사용가능)

mysql> SELECT ALL name FROM sample51;
mysql> SELECT DISTINCT name FROM sample51;
생략시 ALL로 간주

-DISTINCT를 이용해 중복되지 않는 데이터 개수 구하기 집계함수의 인수로 DISTINCT사용

mysql> SELECT COUNT(DISTINCT name) FROM sample51;

[SUM]

수치형 집합만 지정가능, NULL값 무시

mysql> SELECT SUM(quantity) FROM sample51;
+---------------+
| SUM(quantity) |
+---------------+
|            16 |
+---------------+

[AVG]

mysql> SELECT AVG(quantity) FROM sample51;
+---------------+
| AVG(quantity) |
+---------------+
|        4.0000 |
+---------------+

-NULL을 0으로 계산하기

mysql> SELECT AVG(CASE WHEN quantity IS NULL THEN 0 ELSE quantity END) FROM sample51;

[MIN MAX]

문자열형,날짜시간형에도 사용가능 NULL값 무시

mysql> SELECT MAX(quantity) FROM sample51;
+---------------+
| MAX(quantity) |
+---------------+
|            10 |
+---------------+
1 row in set (0.01 sec)

mysql> SELECT MIN(quantity) FROM sample51;
+---------------+
| MIN(quantity) |
+---------------+
|             1 |
+---------------+
mysql> SELECT MIN(CASE WHEN quantity IS NULL THEN 0 ELSE quantity END) FROM sample51;

[그룹화]

집계함수의 활용범위를 넓힐 수 있음

-GROUP BY구 : 지정된 열의 값이 같은 행이 하나의 그룹으로 묶임
지정하지 않은 열은 SELECT에서 사용X (집계함수와 사용은 가능)
GROUP BY는 그룹화된 각각의 그룹이 하나의 집합으로 집계함수의 인수로 넘겨짐

+------+----------+
| name | quantity |
+------+----------+
| A    |        1 |
| A    |        2 |
| B    |       10 |
| C    |        3 |
| NULL |     NULL |
+------+----------+
mysql> SELECT name FROM sample51 GROUP BY name;
+------+
| name |
+------+
| A    |
| B    |
| C    |
| NULL |
+------+

집계함수와 사용
mysql> SELECT name,COUNT(name),SUM(quantity) FROM sample51 GROUP BY name;
+------+-------------+---------------+
| name | COUNT(name) | SUM(quantity) |
+------+-------------+---------------+
| A    |           2 |             3 |
| B    |           1 |            10 |
| C    |           1 |             3 |
| NULL |           0 |          NULL |
+------+-------------+---------------+

-내부처리순서
WHERE -> GROUP BY -> SELECT -> ORDER BY

때문에 다음과 같이 사용할 수 없다. => WHERE구에서 집계함수 사용 X

mysql> SELECT name, COUNT(name), SUM(quantity) FROM sample51 WHERE COUNT(name)=1 GROUP BY name;

-HAVING구
WHERE구와 동일하게 조건식을 지정
조건식에는 집계된 열의 값이나 집계함수의 계산결과가 전달됨

mysql> SELECT name FROM sample51 GROUP BY name HAVING COUNT(name)>1;

[서브쿼리]

SELECT명령에 의한 데이터 질의로, 상부가 아닌 하부의 부수적인 질의를 의미

mysql에서는 데이터를 추가하거나 갱신할 경우 동일한 테이블을 서브쿼리에서 사용할 수 없음

[상관서브쿼리]

-EXISTS(SELECT) : 반환된 행이 있다면 참, 없다면 거짓을 반환 => SELECT가 스칼라 값을 반환하지 않아도 됨

mysql> SELECT * FROM SAMPLE551 WHERE EXISTS(SELECT * FROM SAMPLE552 WHERE no2 = no);
552.no2 = 551.no인 행을 반환

mysql> SELECT * FROM SAMPLE551 WHERE NOT EXISTS(SELECT * FROM SAMPLE552 WHERE no2 = no);
552.no2 = 551.no가 아닌 행을 반환

다음과 같이 SET구에서도 EXISTS와 CASE를 사용해 업데이트를 할 수 있음
mysql> UPDATE SAMPLE551 SET a = (CASE WHEN EXISTS(SELECT * FROM SAMPLE552 WHERE no2=no) THEN '있음1' ELSE '없음1' END);

UPDATE명령(부모)과 서브쿼리(자식)처럼, 부모명령과 자식인 서브쿼리가 특정 관계를 맺는 것을 ‘상관 서브쿼리’라 부름

두 테이블의 열이 같은 이름이라면(EX. board_id, board_id) 에러 혹은 같은 테이블의 열을 가리켜 항상 참이 됨.
이를 해결하기위해 열명 앞에 ‘테이블명.’ 을 붙여주면 됨
table1.board_id = table2.board_id

만약 열명이 같고 명시하지 않는다면, 가장 가까운 스코프에 있는 열로 인식하고 처리함
그렇기에 해당 쿼리의 열은 명시를 하지 않아도 상관은 없으나 가독성을 위해 명시하자!

-IN
열명 IN(집합)
스칼라 값끼리 비교시 =를 사용했다면, 집합을 비교할 때는, IN으로 집합 안에 값이 존재하는 지 조사할 수 있다.

테이블이 다음과 같을 때
551
+------+-------+
| no   | a     |
+------+-------+
|    1 | 없음1 |
|    2 | 없음1 |
|    3 | 있음1 |
|    4 | 없음1 |
|    5 | 있음1 |
+------+-------+
552
+------+
| no2   | 
+------+
|    3 | 
|    5 | 
+------+
mysql> SELECT * FROM551 WHERE no IN(3,5);
mysql> SELECT * FROM551 WHERE no IN(SELECT no2 FROM 552);

집합부분을 서브쿼리로 지정할 수도 있음

-NOT IN

-IN과 NULL