SQL - PostgreSQL, Function, Procedure

2026. 4. 1. 16:06·🧩 SQL

PostgreSQL

 

 

✅ Function & Procedure


Function과 Procedure는 Database Object다.

이 둘을 이용하면 특정 작업을 수행하는 SQL구문을 세트로 캡슐화 할 수 있다.

(재사용 가능)

 

 

✅ Function


Function은 반드시 value를 return한다.

(Procedure와의 가장 큰 차이점)

 

DML(Data Manipulation Language) Command에서 사용하기 위한 것

CREATE OR REPLACE FUNCTION hello_world ()
RETURNS TEXT AS
$$
	SELECT 'hello_world';
$$
LANGUAGE SQL;

LANGUAGE 키워드로 어떤 언어로 Function이 작성 되었는지 적어줘야 한다.

 

CREATE OR REPLACE FUNCTION public.hello_world()
 RETURNS text
 LANGUAGE sql
AS $function$
	SELECT 'hello_world';
$function$

생성된 Function 모습

Function은 default로 public schema에 생성된다.

 

Function 호출방법

CREATE OR REPLACE FUNCTION hello_world (user_name TEXT)
RETURNS TEXT AS
$$
	SELECT 'hello ' || user_name;
$$
LANGUAGE SQL;

SELECT
	title,
	hello_world ('nico')
FROM
	movies;

Function의 arg에 arg를 안 넣어서 호출한다고 해서 Error가 나는 것이 아니라 잘 실행이 된다.(hello world가 나옴)

 

그 이유는 사실 PostgreSQL이 이름이 같다는 이유로 Function을 다르게 보지 않기 때문.

그래서 Functions를 확인해보면 같은 이름의 함수 2개가 존재하게 되고 arg가 없는 버전의 Function이 실행이 된 것.

 

 

arg를 이름 지정 없이 받는 법

CREATE
OR REPLACE FUNCTION hello_world (TEXT, TEXT) RETURNS TEXT AS $$
	SELECT 'hello ' || $1 || ' and ' || $2;
$$ LANGUAGE SQL;

SELECT
	hello_world ('nico', 'lynn');

 

 

Function에서 return 값을 Table로 주는 방법과 해당 Table의 column을 분리해서 나타내는 법

CREATE
OR REPLACE FUNCTION is_hit_or_flop (movie movies) RETURNS TABLE (hit_or_flop TEXT, other_thing NUMERIC) AS $$
	SELECT CASE
		WHEN movie.revenue > movie.budget THEN 'Hit'
		WHEN movie.revenue < movie.budget THEN 'Flop'
		ELSE 'N/A'
	END, 1515;
$$ LANGUAGE SQL;


SELECT
	title,
	(is_hit_or_flop (movies.*)).*
FROM
	movies;

 

 

Volatility

Volatility: optimizer에게 function의 동작에 대한 약속을 하는 것

기본적으로 함수를 만들면 Volatility는 Volatile이 된다.

 

Options

1. VOLATILE (default)

database를 수정하는 것을 포함해서 모든 것을 할 수 있다. (record를 지우거나 업데이트 하는 등)

VOLATILE Function은 같인 arg를 넣어도 다른 결과를 return한다.

 

2. STABLE

database를 수정할 수 없는 Function.

단일 구문 내의 모든 row에서 동일한 arg에 대해서는 같은 결과를 return한다.

Function을 이 카테고리로 설정하면 optimizer가 복수의 실행을 하나의 실행으로 최적화 해준다.

 

3. IMMUTABLE

database를 수정할 수 없는 Function

동일한 arg가 주어질 경우 영원히 같은 결과를 return한다.

상수 arg와 함께 호출 되면 optimizer가 function을 미리 평가할 수 있게 해준다.

 

 

Using Function with Trigger

CREATE
OR REPLACE FUNCTION set_updated_at () RETURNS TRIGGER AS $$
	BEGIN
		NEW.updated_at = CURRENT_TIMESTAMP;
		RETURN NEW;
	END;
$$ LANGUAGE plpgsql; -- Trigger를 사용해야 하기 때문에 sql이 아닌 plpgsql을 사용한다.

CREATE TRIGGER updated_at
BEFORE UPDATE -- OF를 사용해서 특정 column만을 위한 Trigger를 만들 수도 있다.
ON movies FOR EACH ROW
EXECUTE PROCEDURE set_updated_at();

 

 

✅ Procedure


Function과 Procedure는 비슷하면서도 다르다.

둘 다 SQL command 뭉치를 캡슐화 해준다는 점에서는 비슷하다.

 

Procedure는 Function과 같은 이름을 가질 수 없다.

 

Function과의 차이점

Function은 반드시 뭔가를 return해야 한다.

하지만 Procedure는 return을 할 수는 있지만 필수가 아니다.

 

Function은 DML command 안에서 호출된다.
Procedure는 DML command 안에서 호출하지 않는다.

CALL 뒤에 Procedure의 이름을 붙여서 호출한다.

Procedure 생성

CREATE OR REPLACE PROCEDURE set_zero_revenue() AS
$$
	UPDATE movies SET revenue = NULL WHERE revenue = 0;
$$
LANGUAGE SQL;

 

Procedure 호출

CALL set_zero_revenue ();

 

return값 있는 Procedure

CREATE OR REPLACE PROCEDURE hello_world_p(IN name TEXT, OUT greeting TEXT) AS
$$
	BEGIN
		greeting = 'Hello' || name;
	END;
$$
LANGUAGE plpgsql;

CALL hello_world_p ('nico', NULL);

output도 넣어서 호출해야 하기 때문에 NULL값을 넣어준다.

 

plpgsql(Procedural Language Postgre SQL)로 SQL 방식보다 Programming 방식으로 작성하기

CREATE
OR REPLACE PROCEDURE hello_world_i (IN name TEXT, IN lang TEXT, OUT greeting TEXT) AS $$
	DECLARE spanish_hello TEXT := 'hola';
	italian_hello TEXT := 'ciao';
	korean_hello TEXT := '안녕';
	BEGIN
		IF lang = 'korean' THEN
			greeting := korean_hello || ' ' || name || '!';
		ELSIF lang = 'italian' THEN
			greeting := italian_hello || ' ' || name || '!';
		ELSIF lang = 'spanish' THEN
			greeting := spanish_hello || ' ' || name || '!';
		ELSE
			greeting := 'hello ' || name || '!';
		END IF;
	END;
$$ LANGUAGE plpgsql;

CALL hello_world_i ('nico', 'spanish', NULL);

plpgsql을 사용할 때는 BEGIN과 END를 필수로 사용해야 한다. (Trigger를 사용해야 할 때도 plpgsql로 작성해야 한다.)

'🧩 SQL' 카테고리의 다른 글

SQL - PostgreSQL, Transaction, Save Point, Isolation Level, Phenomena  (0) 2026.04.02
SQL - PostgreSQL, Extension(plpython3)  (0) 2026.04.02
SQL - PostgreSQL, UNNEST, DISTINCT, FULL OUTER JOIN  (0) 2026.04.01
SQL - PostgreSQL, Data Types  (0) 2026.04.01
SQL - PostgreSQL, pgAdmin  (0) 2026.04.01
'🧩 SQL' 카테고리의 다른 글
  • SQL - PostgreSQL, Transaction, Save Point, Isolation Level, Phenomena
  • SQL - PostgreSQL, Extension(plpython3)
  • SQL - PostgreSQL, UNNEST, DISTINCT, FULL OUTER JOIN
  • SQL - PostgreSQL, Data Types
j2yonghwa
j2yonghwa
Trying to be a fullstack developer 🚀
  • j2yonghwa
    j2yonghwa
    j2yonghwa
  • 전체
    오늘
    어제
    • 분류 전체보기 (156)
      • ⏰ Daily WakaTime (1)
      • 🏖️ 노마드코더 (2)
      • 🍺 Dev Setup (3)
      • 🔭 Tech Info (1)
      • 🚫 Error (1)
      • 📂 라이브러리 (23)
      • ♣️ Next.js 14 (10)
      • ♠️ Next.js 12 (20)
      • 🛸 React Native (12)
      • 🦋 TypeScript (1)
      • 🐍 Python (2)
      • 🌊 TailwindCSS (4)
      • 🧩 SQL (25)
      • 💎 Prisma (5)
      • 🌱 MongoDB (4)
      • 🎯 Redis (1)
      • 🧬 GraphQL (2)
      • 🔥 Firebase (7)
      • 💸 Third-Party Services (2)
      • 🕸️ Web (1)
      • 🏆 코딩테스트 (23)
      • 📙 모딥다 (5)
      • 📗 코테 합격자 되기 -JS- (0)
      • 📘 클린코드 (0)
      • 🍯 꿀팁 🐝 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃헙
  • 공지사항

  • 인기 글

  • 태그

    코딩테스트 입문
    MySQL
    API
    Next.js
    next.js 14
    SQL
    모딥다
    Prisma
    React Native
    next.js 12
    PostgreSQL
    react router
    라이브러리
    Firebase
    tailwindcss
    dev setup
    Python
    0레벨
    mongoDB
    자바스크립트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
j2yonghwa
SQL - PostgreSQL, Function, Procedure
상단으로

티스토리툴바