ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SQL 서브쿼리_2
    Database 2021. 4. 14. 16:00
    728x90

    SELECT 구 + 서브쿼리

    서브쿼리는 WHERE 구, SELECT 구, UDDATE의 SET구 등 다양한 구 안에서 사용이 가능하다.

    문법적으로 서브쿼리는 하나의 항목으로 취급한다. 단, 문법적으로는 문제가 없어도 실행하면 에러가 발생하는 경우가 종종있는데 이는 서브쿼리가 스칼라 서브쿼리 (하나의 값만 반환하는지)에 대해 생각해볼 필요가 있으며 서브쿼리를 사용할 때는 스칼라 서브쿼리로 되어있어야한다.

    즉, SELECT 구 + 서브쿼리를 지정할때 스칼라 서브쿼리가 필요하다.

    각 테이블의 행의 개수를 나타내보자.

    SELECT
        (SELECT COUNT(*) FROM 테이블명) AS 별명,
        (SELECT COUNT(*) FROM 테이블명2) AS 별명2;

    여기서 주의할점

    FROM이 생략되었다는 것이다.

    MySQL에서는 실제로 FROM을 생략할 수 있기 때문인데, Oracle에서는 FROM을 생략할 수 없기 때문에 아래와 같이 나타낼수 있다.

    (MySQL에서도 동작한다.)

    SELECT
        (SELECT COUNT(*) FROM 테이블명) AS 별명,
        (SELECT COUNT(*) FROM 테이블명2) AS 별명2 FROM DUAL;


    SET구 + 서브쿼리

    UPDATE의 SET구에서도 서브쿼리를 사용할 수 있다.

    이때도 스칼라 서브쿼리를 지정해줘야 한다. 

    아래는 예제일뿐 실제로 이런 명령은 사용하지 않는다고 한다.

    모든 a열의 값이 모두 a열의 최댓값으로 갱신된다. 이때 서브쿼리는 상부의 UPDATE 명령과 관련이 있는 조건식으로 지정하지 않으면 의미가 없다고 한다. 추후 뒷장에서 추가로 알아보도록 하자.

    SELECT 테이블명 SET a = (SELECT MAX(a) FROM 테이블명);

    FROM구 + 서브쿼리

    앞선 예제와 달리 FROM 구에서 테이블 이외 것도 지정해보자.

    이때 FROM구는 기본적으로 테이블을 지정하는 만큼 다른 구와는 조금 다르다.

    FROM구의 서브쿼리에서는 스칼라 서브쿼리가 아니라도 문제가 되지 않는다.

     

    SELECT 명령 안에 SELECT 명령이 들어있는 듯 보이며

    이를 네스티드(nested) 구조 또는 중첩구조 또는 내포구조라 부른다.

    여기서 SELECT 구에서 열이나 식에 별명을 붙이듯 FROM 구에서는 테이블이나 서브쿼리에 별명을 붙힐 수 있는데

    이때 별명은 FROM 구에서의 별명을 나타내는 것으로 서브쿼리의 이름을 지정한다는 점을 확인할 수 있다.

    (AS 를 붙히면 Oracle에서는 에러가 발생한다고 한다.)

    SELECT * FROM
      (SELECT * FROM 테이블명) 별명; # AS 별명 => Oracle 에러 발생

    아래와 같이 중첩구조를 몇 단계로든 구성할 수 있다.

    SELECT * FROM
      (SELECT * FROM 
        (SELECT * FROM 테이블명) 별명) 별명2;

    사실 위 명령은 SELECT 로 테이블 하나를 나타내는 명령과 결과가 다르지 않다.

    이렇게 3단계로도 중첩구조를 작성한다는 것만 이해하자. 실제로는 의미가 없는 명령이다.


    INSERT 명령 + 서브쿼리

    1. VALUES 구의 일부로 서브쿼리를 사용하는 방법과

    2. VALUES 대신 SELECT 구 명령을 사용하는 방법

    총 2가지 방법이 있다.


    1. VALUES 구 + 서브쿼리

    스칼라 서브쿼리와 함께 자료형도 일치시켜야 올바르게 동작한다.

    INSERT INTO 테이블명 VALUES(
      (SELECT COUNT(*) FROM 테이블명1),
      (SELECT COUNT(*) FROM 테이블명2)
     );
     SELECT * FROM 테이블명; -> INSERT 결과 확인을 위함

     

    insert values 구를 이용해 값을 하나 추가해보도록 하자

    insert into ttt_set values(
        4,
        (select count(*) from products),
        "TEST"
        );
        
    select * from ttt_set;


    2. INSERT SELECT + 서브쿼리(?)

    VALUES 구 대신 SELECT 구를 사용하는 방법이다.

    이는 괄호를 붙히지 않아 서브쿼리라고 부리기 어려울 수 있는 방법이라고 한다.

    INSERT INTO 테이블명 SELECT 값1, 값2;
    SELECT * FROM 테이블명; => 결과 확인을 위함

    흔히 INSERT SELECT 라 불리는 명령으로 둘을 합친 것과 같다.

    SELECT 의 결과값으로 값1, 값2가 반환되므로 아래와 같다.

    INSERT INTO 테이블명 SELECT 1, 2;
    => INSERT INTO 테이블명 VALUES (1, 2);인 경우와 같다.

    이때, SELECT 명령이 반환하는 값은 스칼라 서브쿼리가 아니여도 문제 없다.

    SELECT가 반환하는 열 수와 자료형이 INSERT 할 테이블과 일치하기만 하면 된다.


    테이블의 행 복사하기?

    INSERT SELECT 명령은

    SELECT의 결과를 INSERT INTO로 지정한 테이블에 전부 추가한다.

    SELECT 명령을 클라이언트로 반환하지 않고 지정된 테이블에 추가하는 것이다.

    이러한 특성을 이용해서 실제로는 데이터의 복사나 이동을 할때 자주 사용되는 명령이라 한다.

    여기서 주의할점은 열 구성이 동일한 테이블 사이에서 복사가 가능하다는 점이다.

    INSERT INTO 복사할 테이블명 SELECT * FROM 덤프할 테이블명;

     

    출처 :

    SQL 첫걸음/ 아사이 아츠시 지음/ 한빛미디어

    728x90

    'Database' 카테고리의 다른 글

    SQL 데이터베이스 객체  (0) 2021.04.25
    SQL 상관 서브쿼리  (0) 2021.04.19
    SQL 서브쿼리_1  (0) 2021.04.09
    SQL GROUP BY  (0) 2021.04.09
    SQL COUNT 집계함수  (0) 2021.03.29
Designed by Tistory.