MySQL과 PostgreSQL의 데이터 처리 비교: RETURNING 절과 CTE

4818 단어
"MySQL과 PostgreSQL의 데이터 비교"라는 제목의 제 마지막 게시물에 대한 후속 조치로, 실제로 데이터 작업과 관련하여 이 두 데이터베이스 간의 몇 가지 차이점에 대해 논의하고 싶습니다. 그리고 내 이전 게시물과 마찬가지로 이러한 관찰 중 많은 부분이 PostgreSQL이 제공할 수 있는 이점에 대해 계몽되었습니다.

MySQL 작업의 한 가지 주요 불편은 방금 삽입된 행을 가져오기 위해 추가 쿼리를 실행해야 한다는 것입니다. 기껏해야 MySQL은 가장 최근에 삽입된 행의 id만 반환하고 추가 열은 반환하지 않습니다(id는 자동 증분되어 사용자가 그것이 무엇인지 모를 것이기 때문에 중요합니다). 예를 들어 node.js에서 MySQL을 사용하는 경우 INSERT 쿼리는 다음과 같은 json 메시지를 반환합니다. 여기서 삽입된 행의 ID는 6입니다.

{
    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 6,
    "serverStatus": 3,
    "warningCount": 0,
    "message": "",
    "protocol41": true,
    "changedRows": 0
}


그러나 명령줄 MySQL에서는 LAST_INSERT_ID() 함수를 사용하여 해당 ID를 얻기 위해 쿼리를 실행해야 합니다.

mysql> SELECT LAST_INSERT_ID();
       +------------------+
       | LAST_INSERT_ID() |
       +------------------+
       |                6 |
       +------------------+
       1 row in set (0.03 sec)


...그런 다음 행에서 다른 열을 가져오려면 여전히 다른 쿼리를 수행해야 합니다.

그러나 PostgreSQL에는 믿을 수 없을 정도로 합리적인RETURNING 절이 있으며, 이 절은 그것에 대해 알지 않고는 살 수 없습니다(유죄). RETURNING는 본질적으로 INSERT 쿼리에서 SELECT 쿼리로 직접 연결되어 삽입된 행의 어떤 부분이 반환되고 어떻게 반환되는지 결정합니다. 다음은 PostgreSQL 데이터베이스sports의 예입니다. 여기서 스포츠는 테이블sports에 삽입되고 해당 ID는 name(별칭 "sportName ")와 함께 반환되지만 season는 반환되지 않습니다. ) :

sports=# INSERT INTO sports(name, season)
         VALUES('football', 'fall')
         RETURNING sports.id, sports.name AS "sportName";

         id | sportName 
         ----+-----------
           3 | football
         (1 row)

         INSERT 0 1


RETURNING는 무시하기 어려운 이 두 데이터베이스 간의 기능상의 미묘하지 않은 차이입니다. 그러나 그 기능은 공통 테이블 표현식을 고려할 때 더 많은 영향을 미칩니다. CTE는 본질적으로 사용자에게 매우 읽기 쉬운 코드 블록을 제공하는 하위 쿼리의 별칭을 지정하는 수단입니다. MySQL과 Postgres에는 모두 CTE가 있지만 Postgres의 RETURNING 절과 결합하면 CTE는 여러 트랜잭션 없이 간소화된 순차 삽입을 수행할 수 있습니다. 아래 예에서는 CTE를 사용하여 이전에 추가한 스포츠의 id를 얻은 다음 선택한 스포츠의 id를 외래 키id_sport로 하여 새 리그 'NFL'을 삽입하고 리그가 존재하면 팀은 리그의 id와 스포츠의 id를 사용하여 삽입됩니다.

sports=# WITH sport AS (
           SELECT id
           FROM sports
           WHERE name = 'football'
         ), league AS (
           INSERT INTO leagues (name, id_sport, level)
           VALUES ('NFL', (SELECT sport.id FROM sport), 'professional')
           RETURNING id, id_sport
         )
         INSERT INTO teams (designation, nickname, id_sport, id_league)
         SELECT 'New Orleans', 'Saints', sport.id, league.id
         FROM sport
         JOIN league ON TRUE
         RETURNING * \gx

         -[ RECORD 1 ]------------
         id          | 7
         designation | New Orleans
         nickname    | Saints
         id_sport    | 3
         id_league   | 2

         INSERT 0 1


MySQL에서 동일한 작업을 수행하는 것은 다음 예와 같을 수 있습니다. 리그가 삽입된 다음 새 쿼리에서 방금 삽입된 리그의 id가 팀을 삽입하기 위한 외래 키로 사용하도록 선택됩니다. 그리고 id 이상의 정보가 팀에 필요한 경우 당연히 다른 쿼리를 해야 합니다.

mysql> INSERT INTO leagues (name, id_sport, level)
    -> VALUES ('NFL', (
    ->     SELECT sports.id
    ->     FROM sports
    ->     WHERE name = 'football'
    ->   ), 'professional');
       Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO teams (designation, nickname, id_sport, id_league)
    -> SELECT 'New Orleans', 'Saints', (
    ->     SELECT sports.id
    ->     FROM sports
    ->     WHERE name = 'football'
    ->   ), (
    ->     SELECT LAST_INSERT_ID()
    ->   );
       Query OK, 1 row affected (0.00 sec)
       Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from teams \G
       *************************** 1. row ***************************
                id: 7
       designation: New Orleans
          nickname: Saints
          id_sport: 3
         id_league: 2
       1 row in set (0.00 sec)


차이점이 사소해 보일 수 있지만 Postgres의 단일 쿼리 기능은 명령줄과 애플리케이션 내에서 쿼리를 작성할 때 상당한 영향을 미칠 수 있습니다. 사실 이것은 내가 다른 것을 알기도 전에 MySQL을 사용할 때 개인적으로 불편을 겪었던 것입니다. 데이터베이스가 논리적으로 할 수 있어야 한다고 생각했던 일 중 일부가 다른 데이터베이스와 함께 실제로 가능하다는 것을 깨닫게 된 것은 이러한 비교를 작성하기 전까지였습니다. 이것은 물론 MySQL이 장점이 없다는 말은 아닙니다(결국 가장 인기 있는 오픈 소스 데이터베이스입니다. 실제로 Postgres보다 두 배 이상 인기가 있습니다). 그러나 때로는 익숙하지 않은 영역으로 확장하여 솔루션을 생성할 수 있습니다. 존재하지 않았을 수 있습니다. 적절하게도 PostgreSQL과 다른 사람들이 관계형 데이터베이스의 경쟁을 없애면서 계속해서 이익을 얻고 있기 때문에 다른 데이터베이스 사용자도 동일한 결론을 내리는 것으로 보입니다.
출처: db-engines.com/

좋은 웹페이지 즐겨찾기