[{"data":1,"prerenderedAt":402},["ShallowReactive",2],{"post-document:\u002Fdb\u002Fpostgresql\u002F2026\u002F07\u002F31\u002Fpsql1\u002F":3},{"id":4,"title":5,"body":6,"categories":386,"date":389,"description":390,"extension":391,"image":392,"key_concepts":392,"last_modified_at":392,"legacyPath":393,"meta":394,"navigation":396,"part":392,"path":397,"published":396,"robots":392,"seo":398,"series":392,"stem":399,"strengths":392,"summary":392,"tags":400,"tradeoffs":392,"__hash__":401},"posts\u002Fposts\u002FData_Science\u002FPostgreSQL\u002F2026-07-31-psql1.md","Psql 함수,프로시져,트리거",{"type":7,"value":8,"toc":365},"minimark",[9,14,18,23,83,87,90,168,175,184,189,192,196,199,254,257,271,275,278,286,289,306,309,313,317,321,325,329,333,337,341,345,349,353,357,361],[10,11,13],"h2",{"id":12},"함수function","함수(Function)",[15,16,17],"p",{},"psql에서 함수의 기본 구조는 다음과 같다.",[19,20,22],"h4",{"id":21},"함수-기본-구조","함수 기본 구조",[24,25,30],"pre",{"className":26,"code":27,"language":28,"meta":29,"style":29},"language-sql shiki shiki-themes github-light github-dark","CREATE OR REPLACE FUNCTION 스키마명.함수명(\n    매개변수명 데이터타입\n)\nRETURNS 반환타입\nLANGUAGE 언어\nAS $$\n    함수 본문\n$$;\n","sql","",[31,32,33,41,47,53,59,65,71,77],"code",{"__ignoreMap":29},[34,35,38],"span",{"class":36,"line":37},"line",1,[34,39,40],{},"CREATE OR REPLACE FUNCTION 스키마명.함수명(\n",[34,42,44],{"class":36,"line":43},2,[34,45,46],{},"    매개변수명 데이터타입\n",[34,48,50],{"class":36,"line":49},3,[34,51,52],{},")\n",[34,54,56],{"class":36,"line":55},4,[34,57,58],{},"RETURNS 반환타입\n",[34,60,62],{"class":36,"line":61},5,[34,63,64],{},"LANGUAGE 언어\n",[34,66,68],{"class":36,"line":67},6,[34,69,70],{},"AS $$\n",[34,72,74],{"class":36,"line":73},7,[34,75,76],{},"    함수 본문\n",[34,78,80],{"class":36,"line":79},8,[34,81,82],{},"$$;\n",[19,84,86],{"id":85},"예시-함수-작성","예시 함수 작성",[15,88,89],{},"예를 들어 고객 등급에 따른 할인율 반환하는 함수는 다음과 같이 작성할 수 있다.",[24,91,93],{"className":26,"code":92,"language":28,"meta":29,"style":29},"CREATE OR REPLACE FUNCTION proc_lab.fn_grade_discount_rate(\n    p_grade text\n)\nRETURNS numeric\nLANGUAGE sql\nAS $$\n    SELECT CASE UPPER(TRIM(p_grade))\n        WHEN 'BASIC' THEN 0\n        WHEN 'SILVER' THEN 0.05\n        WHEN 'GOLD' THEN 0.10\n        WHEN 'VIP' THEN 0.15\n        ELSE 0\n    END;\n$$;\n",[31,94,95,100,105,109,114,119,123,128,133,139,145,151,157,163],{"__ignoreMap":29},[34,96,97],{"class":36,"line":37},[34,98,99],{},"CREATE OR REPLACE FUNCTION proc_lab.fn_grade_discount_rate(\n",[34,101,102],{"class":36,"line":43},[34,103,104],{},"    p_grade text\n",[34,106,107],{"class":36,"line":49},[34,108,52],{},[34,110,111],{"class":36,"line":55},[34,112,113],{},"RETURNS numeric\n",[34,115,116],{"class":36,"line":61},[34,117,118],{},"LANGUAGE sql\n",[34,120,121],{"class":36,"line":67},[34,122,70],{},[34,124,125],{"class":36,"line":73},[34,126,127],{},"    SELECT CASE UPPER(TRIM(p_grade))\n",[34,129,130],{"class":36,"line":79},[34,131,132],{},"        WHEN 'BASIC' THEN 0\n",[34,134,136],{"class":36,"line":135},9,[34,137,138],{},"        WHEN 'SILVER' THEN 0.05\n",[34,140,142],{"class":36,"line":141},10,[34,143,144],{},"        WHEN 'GOLD' THEN 0.10\n",[34,146,148],{"class":36,"line":147},11,[34,149,150],{},"        WHEN 'VIP' THEN 0.15\n",[34,152,154],{"class":36,"line":153},12,[34,155,156],{},"        ELSE 0\n",[34,158,160],{"class":36,"line":159},13,[34,161,162],{},"    END;\n",[34,164,166],{"class":36,"line":165},14,[34,167,82],{},[169,170,171],"ul",{},[172,173,174],"li",{},"함수 호출",[24,176,178],{"className":26,"code":177,"language":28,"meta":29,"style":29},"SELECT proc_lab.fn_grade_discount_rate(' gold ');\n",[31,179,180],{"__ignoreMap":29},[34,181,182],{"class":36,"line":37},[34,183,177],{},[185,186,188],"h3",{"id":187},"sql-함수와-plpgsql-함수","SQL 함수와 PL\u002FpgSQL 함수",[15,190,191],{},"PostgreSQL 함수는 본문을 어떤 언어로 작성하는지에 따라 실행 방식이 달라지는데요, 이번에는 LANGUAGE sql 과 LANGAUGE plpgsql을 사용했습니다.",[185,193,195],{"id":194},"sql-함수","SQL 함수",[15,197,198],{},"LANGUAGE sql 함수는 일반적으로 하나의 SQL 문장이나 비교적 단순한 조회 로직을 작성할 때 사용합니다",[24,200,202],{"className":26,"code":201,"language":28,"meta":29,"style":29},"create or replace function proc_lab.fn_grade_discount_rate(\n    p_grade text\n)\nreturns numeric \nLANGUAGE sql \nAS $$\n    SELECT CASE UPPER(TRIM(p_grade))\n        WHEN 'GOLD' THEN 0.10 \n        ELSE 0 \n    END; \n$$; \n",[31,203,204,209,213,217,222,227,231,235,240,245,250],{"__ignoreMap":29},[34,205,206],{"class":36,"line":37},[34,207,208],{},"create or replace function proc_lab.fn_grade_discount_rate(\n",[34,210,211],{"class":36,"line":43},[34,212,104],{},[34,214,215],{"class":36,"line":49},[34,216,52],{},[34,218,219],{"class":36,"line":55},[34,220,221],{},"returns numeric \n",[34,223,224],{"class":36,"line":61},[34,225,226],{},"LANGUAGE sql \n",[34,228,229],{"class":36,"line":67},[34,230,70],{},[34,232,233],{"class":36,"line":73},[34,234,127],{},[34,236,237],{"class":36,"line":79},[34,238,239],{},"        WHEN 'GOLD' THEN 0.10 \n",[34,241,242],{"class":36,"line":135},[34,243,244],{},"        ELSE 0 \n",[34,246,247],{"class":36,"line":141},[34,248,249],{},"    END; \n",[34,251,252],{"class":36,"line":147},[34,253,82],{},[15,255,256],{},"SQL 함수는 다음과 같은 경우에 적합합니다.",[169,258,259,262,265,268],{},[172,260,261],{},"단순 값 계산",[172,263,264],{},"조건에 따른 값 반환",[172,266,267],{},"테이블 조회 결과 반화",[172,269,270],{},"복잡한 데이터 제어가 필요하지 않은 경우",[19,272,274],{"id":273},"plpgsql-함수","PL\u002FpgSQL 함수",[15,276,277],{},"LANGUAGE plpgsql 함수는 PostgreSQL의 절차형 언어를 사용한다.\n변수 선언, 조건문, 예외 처리처럼 일반 SQL으로 표현하기 어려운 로직을 작성할 수 있다.",[24,279,284],{"className":280,"code":282,"language":283},[281],"language-text","CREATE OR REPLACE FUNCTION proc_lab.fn_customer_order_summary_json(\n    p_customer_id bigint\n)\nreturns jsonb \nLANGUAGE plpgsql \nAS $$ \nDECLARE \n    v_customer jsonb; \nBegin \n    select jsonb_build_object(\n        'customer_id', c.customer_id, \n        'name', c.customer_name \n    )\n    into v_customer \n    from proc_lab.customer c\n    where c.customer_id = p_customer_id; \n\n    if v_customer is null then\n        raise exception 'Customer ID % does not exist', p_customer_id; \n    end if; \n\n    return v_customer; \nend; \n$$; \n\n","text",[31,285,282],{"__ignoreMap":29},[15,287,288],{},"PL\u002FpgSQL은 다음과 같은 경우에 적합하다.",[169,290,291,294,297,300,303],{},[172,292,293],{},"DECLARE를 이용한 변수 선언",[172,295,296],{},"IF, CASE 를 이용한 조건 처리",[172,298,299],{},"여러 SQL 문장 순차 실행",[172,301,302],{},"RAISE EXCEPTION을 이용한 예외 처리",[172,304,305],{},"조회 결과를 변수에 저장하는 SELECT INTO",[15,307,308],{},"정리하자면 단순 조회와 계산에는 SQL 함수가 적합하고, 제어 흐름이나 예외 처리가 필요하다면 PL\u002FpgSQL 함수가 적합하다.",[185,310,312],{"id":311},"단일-값테이블jsonb-반환","단일 값·테이블·JSONB 반환",[185,314,316],{"id":315},"함수-속성과-주요-문법","함수 속성과 주요 문법",[10,318,320],{"id":319},"프로시저procedure","프로시저(Procedure)",[185,322,324],{"id":323},"함수와-프로시저의-차이","함수와 프로시저의 차이",[185,326,328],{"id":327},"in-out-inout-매개변수","IN, OUT, INOUT 매개변수",[185,330,332],{"id":331},"주문-생성-프로시저","주문 생성 프로시저",[185,334,336],{"id":335},"returning-into","RETURNING INTO",[185,338,340],{"id":339},"트랜잭션-기반-테스트","트랜잭션 기반 테스트",[10,342,344],{"id":343},"트리거trigger","트리거(Trigger)",[185,346,348],{"id":347},"트리거의-기본-구조","트리거의 기본 구조",[185,350,352],{"id":351},"oldnewtg_op","OLD·NEW·TG_OP",[185,354,356],{"id":355},"감사-로그-트리거","감사 로그 트리거",[185,358,360],{"id":359},"주문-총액-자동-갱신","주문 총액 자동 갱신",[362,363,364],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":29,"searchDepth":43,"depth":43,"links":366},[367,373,380],{"id":12,"depth":43,"text":13,"children":368},[369,370,371,372],{"id":187,"depth":49,"text":188},{"id":194,"depth":49,"text":195},{"id":311,"depth":49,"text":312},{"id":315,"depth":49,"text":316},{"id":319,"depth":43,"text":320,"children":374},[375,376,377,378,379],{"id":323,"depth":49,"text":324},{"id":327,"depth":49,"text":328},{"id":331,"depth":49,"text":332},{"id":335,"depth":49,"text":336},{"id":339,"depth":49,"text":340},{"id":343,"depth":43,"text":344,"children":381},[382,383,384,385],{"id":347,"depth":49,"text":348},{"id":351,"depth":49,"text":352},{"id":355,"depth":49,"text":356},{"id":359,"depth":49,"text":360},[387,388],"DB","PostgreSQL","2026-07-31 08:00:00 +0900","PostgreSQL 함수, 프로시저와 트리거의 기본 문법과 사용 예시를 정리한다.","md",null,"\u002Fdb\u002Fpostgresql\u002F2026\u002F07\u002F31\u002Fpsql1\u002F",{"layout":395},"post",true,"\u002Fposts\u002Fdata_science\u002Fpostgresql\u002F2026-07-31-psql1",{"title":5,"description":390},"posts\u002FData_Science\u002FPostgreSQL\u002F2026-07-31-psql1",[388],"Ot0NGVEiggbP17dMorLL1xiIaxqfdR0qGkiC2lTUqsM",1788744788352]