본문 바로가기
SQL

[SQL] PostgreSQL

by busybee-busylife 2025. 3. 7.
728x90

PostgreSQL의 데이터 타입 

기본 타입 

TEXT, VARCHAR... 

 

사용자 정의 타입 

ex) gender_type 

 

TOAST (The Oversized-Attribute Storage Technique)

- 긴 데이터(Large Object)를 효율적으로 저장하기 위한 기술 

- 기본적으로 압축을 사용하여 공간을 절약 

- 긴 내용이 들어가는 경우 'TEXT' 타입으로 선언 -> 데이터베이스가 알아서 압축 or 별도의 테이블로 이동 

 

CREATE TYPE gender_type AS ENUM ('male', 'female');  -- 타입을 먼저 선언 

CREATE TABLE users (
  username CHAR(10) NOT NULL UNIQUE, -- ex) 'dodo'를 입력하면 나머지 6칸은 blank로 저장 
  email VARCHAR(50) NOT NULL UNIQUE, -- 최대 50글자 
  gender gender_type NOT NULL, 
  interests TEXT[] NOT NULL, 
  bio TEXT, 
  profile_photo BYTEA,  -- BYTEA: 대량 데이터 저장(바이너리; 이미지 등) 
  age SMALLINT NOT NULL CHECK (age >= 0), 
  is_admin BOOLEAN NOT NULL DEFAULT FALSE,
  joined_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL, 
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
  birth_date DATE NOT NULL,
  bed_time TIME NOT NULL, 
  graduation_year INTEGER NOT NULL CHECK (graduation_year BETWEEN 1901 AND 2115),
  intership_period INTERVAL  -- 기간 
  );
  

INSERT INTO users (username, email, gender, interests, bio, profile_photo, age, is_admin, joined_at, updated_at, birth_date, bed_time, graduation_year, intership_period) 
VALUES 
  ('dodo', 'dodo@example.com', 'male', ARRAY['coding', 'gaming'], 'I love coding and gaming.', NULL, 25, FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '1999-05-15', '23:30:00', 2021, INTERVAL '6 months'),
  ('mimi', 'mimi@example.com', 'female', ARRAY['reading', 'traveling'], 'A bookworm and an adventurer.', NULL, 30, TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '1994-08-20', '22:00:00', 2015, INTERVAL '1 year');


SELECT joined_at FROM users; 
-- output: 2025-03-06 17:58:41.714378+09

SELECT EXTRACT(YEAR FROM joined_at::DATE) FROM users;  
-- output: 2025

 

 


UNNEST 

array를 row 형태로 풀어준다(개별요소로 반환) 

각 배열 요소가 개별 행으로 출력 

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  username TEXT NOT NULL,
  interests TEXT[]
);

INSERT INTO users (username, interests) 
  VALUES 
    ('dodo', ARRAY['coding', 'gaming', 'music']),
    ('mimi', ARRAY['reading', 'traveling']);
  
SELECT username, unnest(interests) AS interest FROM users;

-- --------------------------------------
 username |  interest  
----------+-----------
 dodo     | coding
 dodo     | gaming
 dodo     | music
 mimi     | reading
 mimi     | traveling
SELECT string_to_array(genres, ',') FROM movies GROUP BY genres;
SELECT UNNEST(string_to_array(genres, ',')) FROM movies GROUP BY genres;
SELECT DISTINCT UNNEST(string_to_array(genres, ',')) FROM movies GROUP BY genres;
-- 중복값 제거 

INSERT INTO genres (name)
  SELECT DISTINCT UNNEST(string_to_array(genres, ',')) FROM movies GROUP BY genres;
-- genres 테이블의 name 칼럼에 값 넣기

 

CREATE TABLE movies_genres (
  movie_id BIGINT NOT NULL,
  genre_id BIGINT NOT NULL,
  createa_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
  PRIMARY KEY (movie_id, genre_id),
  FOREIGN KEY (movie_id) REFERENCES movies (movie_id),
  FOREIGN KEY (genre_id) REFERENCES genres (genre_id)
  );
-- movies와 genres 간 bridge table 만들기 
  
SELECT movies.title, movies.movie_id, genres.genre_id, genres.name
  FROM movies
  JOIN genres ON movies.genres LIKE '%' || genres.name || '%' ;
  -- movies 테이블의 genres 칼럼이 genres 테이블의 name을 포함하는 조건으로 조인 
  
  
INSERT INTO movies_genres ( movie_id, genre_id) 
  SELECT movies.movie_id, genres.genre_id 
  FROM movies
  JOIN genres ON movies.genres LIKE '%' || genres.name || '%' ;
  -- 위에서 추출한 값을 movies_genres 테이블의 값으로 넣기 


ALTER TABLE movies DROP COLUMN genres;

 

 

728x90

'SQL' 카테고리의 다른 글

[SQL] Transaction  (0) 2025.03.10
[SQL] Functions and Procedures  (0) 2025.03.09
[SQL] FULLTEXT INDEX  (0) 2025.03.03
[SQL] 자동실행 기능: Events / Triggers  (1) 2025.03.03
[SQL] Normalization / Union  (0) 2025.02.24