<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>김신건의 로그 - 위키 / sql</title><description>&apos;sql&apos; 카테고리 위키 페이지 최신 업데이트</description><link>https://shinkeonkim.com/</link><language>ko-KR</language><item><title>[SQL] Data Types</title><link>https://shinkeonkim.com/wiki/sql/sql-data-types/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql-data-types/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;SQL 의 컬럼은 &lt;strong&gt;타입&lt;/strong&gt; 을 가진다. 가능한 값의 도메인, 가능한 연산, 정렬 순서, 인덱스 종류, 저장 크기가 타입에 따라 결정된다.&lt;/p&gt;
&lt;p&gt;같은 의미의 타입도 dialect 마다 이름과 동작이 다르다. 표준 SQL 의 타입을 기준으로, [[PostgreSQL]] / [[MySQL]] 의 실용 매핑을 정리.&lt;/p&gt;
&lt;p&gt;전체 SQL 체계는 [[SQL]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;타입-분류&quot;&gt;타입 분류&lt;/h2&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;그룹&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;주요 타입&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;대표 연산&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;숫자&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTEGER&lt;/code&gt;, &lt;code&gt;BIGINT&lt;/code&gt;, &lt;code&gt;NUMERIC&lt;/code&gt;, &lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;산술, 집계, 반올림&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;문자열&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VARCHAR&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;CHAR&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIKE&lt;/code&gt;, 정규식, 연결, 추출&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;부울&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;AND/OR/NOT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;날짜·시간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DATE&lt;/code&gt;, &lt;code&gt;TIME&lt;/code&gt;, &lt;code&gt;TIMESTAMP&lt;/code&gt;, &lt;code&gt;TIMESTAMPTZ&lt;/code&gt;, &lt;code&gt;INTERVAL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;차이, 추출, 절단&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;이진&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BYTEA&lt;/code&gt; (PG), &lt;code&gt;BLOB&lt;/code&gt; (MySQL)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;길이, 해시, 인코딩&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;UUID&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;UUID&lt;/code&gt; (PG), &lt;code&gt;BINARY(16)&lt;/code&gt; / &lt;code&gt;CHAR(36)&lt;/code&gt; (MySQL)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;생성, 비교&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;화폐&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NUMERIC(p, s)&lt;/code&gt;, &lt;code&gt;MONEY&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정밀 산술&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;JSON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt;, &lt;code&gt;JSONB&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;경로 추출, containment&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;배열&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTEGER[]&lt;/code&gt;, &lt;code&gt;TEXT[]&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;슬라이싱, &lt;code&gt;ANY/ALL&lt;/code&gt;, &lt;code&gt;unnest&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;범위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INT4RANGE&lt;/code&gt;, &lt;code&gt;TSRANGE&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;포함, 겹침&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;공간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GEOMETRY&lt;/code&gt;, &lt;code&gt;GEOGRAPHY&lt;/code&gt; (PostGIS)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;거리, 포함, 교차&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;열거&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ENUM&lt;/code&gt; (PG/MySQL)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정렬, 비교&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;숫자-타입&quot;&gt;숫자 타입&lt;/h2&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;표준 / PG&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;크기&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;범위&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;2 B&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;-32,768 ~ 32,767&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTEGER&lt;/code&gt; / &lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;4 B&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;-2³¹ ~ 2³¹ - 1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8 B&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;-2⁶³ ~ 2⁶³ - 1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NUMERIC(p, s)&lt;/code&gt; / &lt;code&gt;DECIMAL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DECIMAL(p, s)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가변&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정밀 (p 자릿수, s 소수점)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;REAL&lt;/code&gt; / &lt;code&gt;FLOAT4&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FLOAT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;4 B&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;단정밀 부동소수&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DOUBLE PRECISION&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8 B&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배정밀 부동소수&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;numeric-vs-double&quot;&gt;NUMERIC vs DOUBLE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 화폐, 회계 → NUMERIC (정밀, 느림)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; invoices&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (total &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NUMERIC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; invoices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SUM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(total) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; invoices;        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 정확히 30.30&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 과학 계산, 통계 → DOUBLE (빠름, 부동소수 오차 OK)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; measurements&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (val &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DOUBLE PRECISION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 0.1 + 0.2 = 0.30000000000000004&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
돈에 &lt;code&gt;FLOAT&lt;/code&gt;/&lt;code&gt;DOUBLE&lt;/code&gt; 절대 금지. 누적 오차 발생.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;자주-쓰는-연산&quot;&gt;자주 쓰는 연산&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ABS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),                              &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       CEIL(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;FLOOR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),                &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 3, 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;       ROUND&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;345&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),                      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 2.35&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       TRUNC(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;99&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),                          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 2 (PG)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       MOD(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),    &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; % &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;       POWER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),                         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 1024&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;       SQRT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), LN(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;718&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;LOG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       RANDOM();                             &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG: 0~1 / MySQL: RAND()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;집계 함수는 [[SQL GROUP BY]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;문자열-타입&quot;&gt;문자열 타입&lt;/h2&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;표준&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;PostgreSQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;비고&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHARACTER(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHAR(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHAR(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;고정, 짧으면 공백 패딩&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHARACTER VARYING(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VARCHAR(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VARCHAR(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가변&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHARACTER LARGE OBJECT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TEXT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;LONGTEXT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;사실상 무제한&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;PostgreSQL 에선 &lt;code&gt;VARCHAR&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;CHAR&lt;/code&gt; 내부 성능 동일, 길이 제약만 차이.
MySQL 에선 &lt;code&gt;VARCHAR&lt;/code&gt; 가 행 안에 저장, &lt;code&gt;TEXT&lt;/code&gt; 는 별도 저장 영역, 성능 차이 있음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;자주-쓰는-연산-1&quot;&gt;자주 쓰는 연산&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 길이&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LENGTH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);                        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 5 (PG, 문자 수)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CHAR_LENGTH(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), OCTET_LENGTH(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;한&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 글자 수 vs 바이트 수&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 연결&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;Hello, &apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;World&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG, MySQL (ANSI_MODE)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; CONCAT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Hello, &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;World&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);             &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 양쪽 모두&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 자르기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SUBSTRING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FOR&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &apos;world&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SUBSTR(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);            &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 같음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 변환&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; UPPER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;LOWER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;ABC&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), INITCAP(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;hello world&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; REPLACE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;a-b-c&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;_&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);             &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &apos;a_b_c&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 트림&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRIM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;  hello  &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;LTRIM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;  hello&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RTRIM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;hello  &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 패딩&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LPAD(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;7&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;0&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);                      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &apos;007&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;like-vs-ilike-vs-정규식&quot;&gt;LIKE vs ILIKE vs 정규식&lt;/h3&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;연산&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;dialect&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIKE &apos;...&apos;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;%&lt;/code&gt;, &lt;code&gt;_&lt;/code&gt; 와일드카드&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ILIKE &apos;...&apos;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;LIKE + 대소문자 무시&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;~&lt;/code&gt;, &lt;code&gt;~*&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정규식 (대소문자 / 무시)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;REGEXP_MATCHES&lt;/code&gt;, &lt;code&gt;REGEXP_REPLACE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정규식 함수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;REGEXP&lt;/code&gt; / &lt;code&gt;RLIKE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정규식&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MySQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;REGEXP_LIKE&lt;/code&gt;, &lt;code&gt;REGEXP_SUBSTR&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정규식 함수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MySQL 8+&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIKE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;A%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 표준&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ILIKE &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;a%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ~&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;^a&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG 정규식&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; REGEXP &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;^A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;부울&quot;&gt;부울&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; flags&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (active &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BOOLEAN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; FALSE);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flags &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (TRUE), (FALSE), (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flags &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; active;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- TRUE 만, NULL 제외&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- BOOLEAN ≡ TINYINT(1), TRUE=1, FALSE=0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; flags&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (active &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TINYINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flags &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; active &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;날짜시간&quot;&gt;날짜·시간&lt;/h2&gt;
&lt;p&gt;가장 함정이 많은 타입. 표준 + dialect 차이가 크다.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;표준 / PG&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;’YYYY-MM-DD’&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;’HH:MM:SS’ (PG: 6 자리 마이크로초)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DATETIME&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;시각 (시간대 없음)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIMESTAMP WITH TIME ZONE&lt;/code&gt; (&lt;code&gt;TIMESTAMPTZ&lt;/code&gt;)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;시각 + UTC 변환 저장&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTERVAL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;(없음)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;기간 (예: &lt;code&gt;INTERVAL &apos;1 day&apos;&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;mysql-의-timestamp&quot;&gt;MySQL 의 TIMESTAMP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;범위 1970-2038 (32-bit Unix time)&lt;/li&gt;
&lt;li&gt;INSERT 시 세션 timezone 으로 해석 → UTC 저장 → SELECT 시 다시 세션 timezone&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DATETIME&lt;/code&gt; 은 timezone 없음, 그대로 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;postgresql-의-timestamptz&quot;&gt;PostgreSQL 의 TIMESTAMPTZ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;항상 UTC 로 저장&lt;/li&gt;
&lt;li&gt;표시는 세션 timezone (&lt;code&gt;SET TIME ZONE &apos;Asia/Seoul&apos;;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;권장: 시각은 항상 &lt;code&gt;TIMESTAMPTZ&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;현재-시각&quot;&gt;현재 시각&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();                          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG: 트랜잭션 시작 시점&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CURRENT_TIMESTAMP;              &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 표준&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CURRENT_DATE, CURRENT_TIME;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CLOCK_TIMESTAMP();              &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG: 진짜 wall clock&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; STATEMENT_TIMESTAMP();          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG: statement 시작 시점&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL: &lt;code&gt;NOW()&lt;/code&gt;, &lt;code&gt;CURRENT_TIMESTAMP()&lt;/code&gt;, &lt;code&gt;SYSDATE()&lt;/code&gt; (실시간), &lt;code&gt;UTC_TIMESTAMP()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;산술&quot;&gt;산술&lt;/h3&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;h3 id=&quot;시간대-함정&quot;&gt;시간대 함정&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG, TIMESTAMP (timezone 없음) 에 TIMESTAMPTZ 를 넣으면 세션 timezone 으로 변환되어 저장&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logs (ts) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2024-01-15 10:00 UTC&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 세션이 Asia/Seoul 이면 &apos;2024-01-15 19:00&apos; 으로 저장 (KST)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 권장: 항상 TIMESTAMPTZ&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN ts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TYPE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TIMESTAMPTZ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ZONE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;UTC&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;json&quot;&gt;JSON&lt;/h2&gt;
&lt;p&gt;웹 백엔드 어디서나 만난다. 인덱싱 가능 여부가 dialect 의 가장 큰 차이.&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;PostgreSQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;타입&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt; (텍스트), &lt;code&gt;JSONB&lt;/code&gt; (바이너리)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt; (바이너리만)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;인덱싱&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSONB&lt;/code&gt; GIN, expression 인덱스&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;generated column + 인덱스&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;containment &lt;code&gt;@&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✗ (대안: &lt;code&gt;JSON_CONTAINS&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;경로 추출&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;-&gt;&lt;/code&gt;, &lt;code&gt;-&gt;&gt;&lt;/code&gt;, &lt;code&gt;#&gt;&lt;/code&gt;, &lt;code&gt;#&gt;&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;-&gt;&lt;/code&gt;, &lt;code&gt;-&gt;&gt;&lt;/code&gt;, &lt;code&gt;JSON_EXTRACT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&amp;#x3C;CodeWithOutput
variants={[
{ language: ‘sql’, label: ‘PostgreSQL’, code: `CREATE TABLE events (id SERIAL PK, payload JSONB);&lt;/p&gt;
&lt;p&gt;INSERT INTO events (payload) VALUES
(’{“user”: 42, “tags”: [“a”,“b”], “meta”: {“ip”: “1.2.3.4”}}‘::jsonb);&lt;/p&gt;
&lt;p&gt;— 경로 추출
SELECT payload -&gt; ‘user’        FROM events;     — 42 (jsonb)
SELECT payload -&gt;&gt; ‘user’       FROM events;     — ‘42’ (text)
SELECT payload #&gt; ‘{meta, ip}’  FROM events;     — 깊은 경로
SELECT payload #&gt;&gt; ‘{meta, ip}’ FROM events;     — ‘1.2.3.4’ (text)&lt;/p&gt;
&lt;p&gt;— 포함 (containment)
SELECT * FROM events WHERE payload @&gt; ’{“user”: 42}’;&lt;/p&gt;
&lt;p&gt;— 인덱스
CREATE INDEX idx_events_payload ON events USING GIN (payload);
CREATE INDEX idx_events_user ON events ((payload -&gt;&gt; ‘user’));&lt;code&gt;},     { language: &apos;sql&apos;, label: &apos;MySQL&apos;, code:&lt;/code&gt;CREATE TABLE events (id INT PK AUTO_INCREMENT, payload JSON);&lt;/p&gt;
&lt;p&gt;INSERT INTO events (payload) VALUES
(’{“user”: 42, “tags”: [“a”,“b”], “meta”: {“ip”: “1.2.3.4”}}’);&lt;/p&gt;
&lt;p&gt;— 경로 추출
SELECT payload -&gt; ‘$.user’           FROM events;     — 42
SELECT payload -&gt;&gt; ‘$.user’          FROM events;     — ‘42’ (unquote)
SELECT JSON_EXTRACT(payload, ‘$.meta.ip’) FROM events;
SELECT payload -&gt;&gt; ‘$.meta.ip’       FROM events;&lt;/p&gt;
&lt;p&gt;— 포함 대안
SELECT * FROM events WHERE JSON_CONTAINS(payload, ‘42’, ‘$.user’);&lt;/p&gt;
&lt;p&gt;— 인덱스 (generated column)
ALTER TABLE events
ADD COLUMN user_id INT
GENERATED ALWAYS AS (payload -&gt;&gt; ‘$.user’) VIRTUAL,
ADD INDEX idx_user_id (user_id);&lt;code&gt; },   ]}   outputLabel=&quot;비고&quot;   output={&lt;/code&gt;— PG 의 JSONB 는 인덱싱과 containment 가 강력
— MySQL 의 JSON 은 generated column 트릭이 필요
— JSON 에 무거운 쿼리를 자주 돌리면 별도 컬럼으로 정규화 검토`}
/&gt;&lt;/p&gt;
&lt;p&gt;JSON 의 &lt;code&gt;tags&lt;/code&gt; 배열을 펼쳐 행으로:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, tag&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events, jsonb_array_elements_text(payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;tags&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tag;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL 8+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;tag&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;JSON_TABLE(payload, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$.tags[*]&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMNS (tag &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PATH&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;$&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[[Pandas explode]] 와 같은 개념.&lt;/p&gt;
&lt;h2 id=&quot;배열-postgresql&quot;&gt;배열 (PostgreSQL)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; posts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SERIAL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PK, tags &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TEXT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts (tags) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ARRAY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&apos;db&apos;, &apos;sql&apos;]), (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;{&quot;db&quot;,&quot;cache&quot;}&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tags @&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ARRAY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&apos;db&apos;];                    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 포함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;sql&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ANY(tags);                       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 멤버&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array_length(tags, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts;                           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 길이&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts, unnest(tags) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;                        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 펼침&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_posts_tags&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; GIN (tags);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL 에는 배열 타입이 없다, 보통 &lt;code&gt;JSON&lt;/code&gt; 으로 흉내.&lt;/p&gt;
&lt;h2 id=&quot;uuid&quot;&gt;UUID&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; EXTENSION &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; EXISTS&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;uuid-ossp&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; users&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id UUID &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uuid_generate_v4());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL 8+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; users&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BINARY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (UUID_TO_BIN(UUID())));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;UUID v4 (랜덤) 는 인덱스 지역성이 나쁘다. 시간 정렬 UUID (v7, ULID) 가 B-tree 친화적.&lt;/p&gt;
&lt;h2 id=&quot;enum&quot;&gt;ENUM&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TYPE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order_status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ENUM (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;pending&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;paid&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;shipped&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;cancelled&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ADD&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order_status;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TYPE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order_status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ADD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; VALUE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;refunded&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 추가&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 값 제거는 직접 불가, 우회 필요&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; orders&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ...,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  status&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ENUM(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;pending&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;paid&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;shipped&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;cancelled&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;MODIFY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;status&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ENUM(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;pending&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;paid&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;shipped&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;cancelled&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;refunded&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 풀 리라이트&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ENUM 은 추가는 쉬워도 변경/제거가 까다롭다. &lt;strong&gt;상태가 자주 변하면 lookup 테이블 + FK 가 더 유연&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;타입-변환-cast&quot;&gt;타입 변환 (CAST)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; CAST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;42&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INTEGER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;42&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL 단축&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 안전한 변환 (실패 시 NULL, PG 17+)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; CAST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INTEGER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ERROR &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 또는 사용자 함수, TRY_CAST 같은 패턴&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- TO_CHAR / TO_DATE / TO_NUMBER (PG, Oracle 영향)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TO_CHAR(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;YYYY-MM-DD HH24:MI&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TO_DATE(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2024-01-15&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;YYYY-MM-DD&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
묵시적 형변환은 &lt;strong&gt;인덱스를 깬다&lt;/strong&gt;. &lt;code&gt;WHERE id = &apos;42&apos;&lt;/code&gt; 가 id 가 정수면 양쪽 모두 INTEGER 로 변환, 인덱스 OK. 하지만 &lt;code&gt;WHERE CAST(id AS TEXT) = &apos;42&apos;&lt;/code&gt; 는 인덱스 못 쓴다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;pandas-와-타입-대응&quot;&gt;pandas 와 타입 대응&lt;/h2&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;SQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;pandas&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;dtype&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTEGER&lt;/code&gt;, &lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;int64&lt;/code&gt;, &lt;code&gt;Int64&lt;/code&gt; (nullable)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;int&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NUMERIC&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Decimal&lt;/code&gt; (object) 또는 &lt;code&gt;float64&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;object/float&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;float64&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;float&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt; (nullable)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;bool&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VARCHAR&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;object&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;string&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;datetime64[ns]&lt;/code&gt; (또는 &lt;code&gt;datetime64[ns, tz]&lt;/code&gt;)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;datetime&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;datetime64[ns]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;datetime&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TIMESTAMPTZ&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;datetime64[ns, UTC]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;datetime tz-aware&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTERVAL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;timedelta64[ns]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;timedelta&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt;, &lt;code&gt;JSONB&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;object&lt;/code&gt; (dict)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ARRAY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;object&lt;/code&gt; (list)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;UUID&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;object&lt;/code&gt; (str)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;DB 와 DataFrame 의 타입 매핑은 [[Pandas read_sql]] 의 &lt;code&gt;dtype_backend&lt;/code&gt;, &lt;code&gt;parse_dates&lt;/code&gt;, &lt;code&gt;dtype=&lt;/code&gt; 옵션 참고.&lt;/p&gt;
&lt;p&gt;[[Pandas nullable]] (&lt;code&gt;Int64&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;) 가 NULL 을 정수/부울에 보존하기 위해 도입되었다.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-varcharn-의-n&quot;&gt;1. VARCHAR(N) 의 N&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;PG: 글자 수, 초과 시 에러&lt;/li&gt;
&lt;li&gt;MySQL: 글자 수, 초과 시 에러 (&lt;code&gt;strict_mode&lt;/code&gt;) 또는 잘림 (&lt;code&gt;non_strict&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;인코딩 (utf8mb4) 차이로 바이트 길이 ≠ 글자 수&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-timestamp-vs-timestamptz&quot;&gt;2. TIMESTAMP vs TIMESTAMPTZ&lt;/h3&gt;
&lt;p&gt;PG 에서 &lt;code&gt;TIMESTAMP&lt;/code&gt; 와 &lt;code&gt;TIMESTAMPTZ&lt;/code&gt; 는 다른 타입. 운영에서 시각은 &lt;strong&gt;항상 &lt;code&gt;TIMESTAMPTZ&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;3-numeric-의-정밀도&quot;&gt;3. NUMERIC 의 정밀도&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NUMERIC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 전체 10 자리, 소수점 이하 2 자리&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 정수부 최대 8 자리, 99999999.99 까지&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-float-의-비교&quot;&gt;4. FLOAT 의 비교&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FLOAT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FLOAT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FLOAT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- FALSE!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 같음 비교는 위험, ABS(a - b) &amp;#x3C; epsilon&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;5-null-의-정렬&quot;&gt;5. NULL 의 정렬&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULLS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LAST&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     -- PG (표준)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     -- MySQL 우회&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;6-묵시적-변환-mysql&quot;&gt;6. 묵시적 변환 (MySQL)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL: 문자열 ↔ 숫자 묵시적 변환&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1a&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 2 (경고만)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;a&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 1 (조용히 0 으로 변환!)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 는 같은 케이스에서 에러. 둘 다 운영 코드에선 명시적 변환 권장.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DDL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[SQL GROUP BY]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;li&gt;[[Pandas nullable]]&lt;/li&gt;
&lt;li&gt;[[Pandas explode]]&lt;/li&gt;
&lt;li&gt;[[Pandas to_datetime]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>data-types</category><category>schema</category><category>database</category><author>koa (김신건)</author></item><item><title>[SQL] DCL TCL</title><link>https://shinkeonkim.com/wiki/sql/sql-dcl-tcl/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql-dcl-tcl/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DCL&lt;/strong&gt; (Data Control Language): &lt;strong&gt;권한&lt;/strong&gt;. &lt;code&gt;GRANT&lt;/code&gt;, &lt;code&gt;REVOKE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCL&lt;/strong&gt; (Transaction Control Language): &lt;strong&gt;트랜잭션 경계&lt;/strong&gt;. &lt;code&gt;BEGIN&lt;/code&gt;, &lt;code&gt;COMMIT&lt;/code&gt;, &lt;code&gt;ROLLBACK&lt;/code&gt;, &lt;code&gt;SAVEPOINT&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;같이 묶어 다루는 이유, “보안”과 “원자성”은 운영의 두 기둥이고 SQL 의 나머지 (DDL/DML) 와 결이 다르다.&lt;/p&gt;
&lt;p&gt;전체 SQL 체계는 [[SQL]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;트랜잭션과-acid&quot;&gt;트랜잭션과 ACID&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;트랜잭션&lt;/strong&gt; = 하나의 논리 단위로 묶인 SQL 문 집합. 전체가 성공하거나 (&lt;code&gt;COMMIT&lt;/code&gt;), 전체가 취소되거나 (&lt;code&gt;ROLLBACK&lt;/code&gt;).&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;성질&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;A&lt;/strong&gt;tomicity&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;원자성, all-or-nothing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;C&lt;/strong&gt;onsistency&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;무결성 제약을 깨지 않음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;I&lt;/strong&gt;solation&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;동시 트랜잭션이 서로 안 보임 (격리 수준 따라)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;D&lt;/strong&gt;urability&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;커밋된 변경은 영구 (장애에도 살아남음)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Redis 의 트랜잭션은 ACID 가 아니다, 자세한 비교는 [[Redis]] 참고.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;begin--commit--rollback&quot;&gt;BEGIN / COMMIT / ROLLBACK&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 트랜잭션 시작 (PG)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;START TRANSACTION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 표준 / MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 확정&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 또는&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROLLBACK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 취소, 둘 다 안 일어난 상태로&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL: &lt;strong&gt;모든 statement 가 암묵적 트랜잭션&lt;/strong&gt;. &lt;code&gt;BEGIN&lt;/code&gt; 명시하면 다중 statement 트랜잭션.&lt;/li&gt;
&lt;li&gt;MySQL: &lt;code&gt;autocommit=1&lt;/code&gt; (기본). statement 마다 자동 커밋. &lt;code&gt;BEGIN&lt;/code&gt;/&lt;code&gt;START TRANSACTION&lt;/code&gt; 으로 묶거나 &lt;code&gt;SET autocommit=0&lt;/code&gt; 후 명시 &lt;code&gt;COMMIT&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;autocommit-의-함정&quot;&gt;autocommit 의 함정&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL 기본 (autocommit=1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 즉시 커밋, 되돌릴 수 없음!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 안전한 방법&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;START TRANSACTION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 확인&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 또는 ROLLBACK&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;운영 DB 에선 항상 명시적 트랜잭션. autocommit 끄는 습관 권장.&lt;/p&gt;
&lt;h2 id=&quot;savepoint&quot;&gt;SAVEPOINT&lt;/h2&gt;
&lt;p&gt;트랜잭션 안에서 부분 롤백 지점.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logs (msg) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;start&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;SAVEPOINT before_risky;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inventory &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; qty &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; qty &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 이상 발견&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROLLBACK&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SAVEPOINT before_risky;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- start log 는 살아 있고 inventory 변경만 취소&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logs (msg) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;skipped risky op&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;격리-수준-isolation-level&quot;&gt;격리 수준 (Isolation Level)&lt;/h2&gt;
&lt;p&gt;동시 트랜잭션 간 가시성. ANSI 표준 4 단계.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;수준&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Dirty Read&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Non-repeatable Read&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Phantom Read&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;READ UNCOMMITTED&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;가능&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;가능&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;가능&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;READ COMMITTED&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;방지&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;가능&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;가능&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;REPEATABLE READ&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;방지&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;방지&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;가능 (표준), 방지 (PG, MySQL InnoDB)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;SERIALIZABLE&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;방지&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;방지&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;방지&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;이상현상&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Dirty Read&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;커밋 안 된 데이터 읽음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Non-repeatable Read&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;같은 쿼리 두 번 → 다른 값&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Phantom Read&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;같은 쿼리 두 번 → 새로 추가된 행 보임&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;dialect-기본값&quot;&gt;dialect 기본값&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;: &lt;code&gt;READ COMMITTED&lt;/code&gt; 기본. &lt;code&gt;REPEATABLE READ&lt;/code&gt;, &lt;code&gt;SERIALIZABLE&lt;/code&gt; 사용 가능 (MVCC + SSI).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL InnoDB&lt;/strong&gt;: &lt;code&gt;REPEATABLE READ&lt;/code&gt; 기본. Phantom 도 방지 (gap lock).&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TRANSACTION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ISOLATION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LEVEL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SERIALIZABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;mvcc-잠금-비교&quot;&gt;MVCC, 잠금, 비교&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;잠금 기반 (Lock-based)&lt;/strong&gt;: 읽는 동안 쓰기 차단. 단순하지만 짧은 쓰기에도 읽기가 막힘.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MVCC&lt;/strong&gt; (Multi-Version Concurrency Control): 트랜잭션마다 자기 버전의 스냅샷을 본다. &lt;strong&gt;읽기가 쓰기를 막지 않고, 쓰기가 읽기를 막지 않는다&lt;/strong&gt;. PostgreSQL, MySQL InnoDB, Oracle 의 기본.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 명시적 행 잠금&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 쓰기 잠금&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FOR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SHARE;      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 읽기 잠금&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG: 다른 트랜잭션 락 충돌 시 즉시 에러&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOWAIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SKIP&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LOCKED;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 큐 패턴&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;데드락&quot;&gt;데드락&lt;/h2&gt;
&lt;p&gt;서로의 락을 기다리는 두 트랜잭션. RDBMS 가 감지해서 한쪽을 강제 롤백.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;T1: UPDATE a; UPDATE b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;T2: UPDATE b; UPDATE a;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   → T1 이 a 잠그고 b 대기, T2 가 b 잠그고 a 대기 → deadlock&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;해법: &lt;strong&gt;항상 같은 순서로 락 획득&lt;/strong&gt;, 또는 짧은 트랜잭션 유지, 또는 비관적 잠금 → 낙관적 잠금 (version 컬럼).&lt;/p&gt;
&lt;h2 id=&quot;dcl-grant--revoke&quot;&gt;DCL: GRANT / REVOKE&lt;/h2&gt;
&lt;p&gt;권한 부여/회수.&lt;/p&gt;
&lt;h3 id=&quot;사용자역할&quot;&gt;사용자/역할&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; USER&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; alice&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WITH&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PASSWORD&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;secret&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ROLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; app_reader;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; app_reader &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; USER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;alice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;@&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; IDENTIFIED &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BY&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;secret&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ROLE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;app_reader&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;app_reader&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TO&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 는 USER 와 ROLE 이 같은 개념 (USER 는 LOGIN 권한이 있는 ROLE), MySQL 도 8.0 부터 통합.&lt;/p&gt;
&lt;h3 id=&quot;권한-부여&quot;&gt;권한 부여&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 테이블 단위&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ALL PRIVILEGES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 스키마 단위 (PostgreSQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; USAGE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SCHEMA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ALL TABLES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SCHEMA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PRIVILEGES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SCHEMA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TABLES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 미래 테이블도 자동 적용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 데이터베이스 단위 (MySQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mydb.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TO&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 모든 데이터베이스 (위험)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ALL PRIVILEGES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TO&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WITH&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; OPTION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;컬럼-단위-권한&quot;&gt;컬럼 단위 권한&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 일부 컬럼만&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;salary 같은 민감 컬럼은 컬럼 단위 + 뷰로 격리하는 게 더 흔하다.&lt;/p&gt;
&lt;h3 id=&quot;revoke&quot;&gt;REVOKE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REVOKE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INSERT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REVOKE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ALL PRIVILEGES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;권한-확인&quot;&gt;권한 확인&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;\dp users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; information_schema&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;table_privileges&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grantee &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;SHOW GRANTS &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;rls-row-level-security-postgresql&quot;&gt;RLS (Row Level Security, PostgreSQL)&lt;/h2&gt;
&lt;p&gt;행 단위 권한, 같은 테이블이라도 사용자에 따라 보이는 행이 다르다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ENABLE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ROW&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LEVEL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SECURITY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; POLICY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; owner_only &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (user_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; current_setting(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;app.user_id&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;세션 변수로 사용자 컨텍스트를 주고 RLS 가 자동으로 &lt;code&gt;WHERE&lt;/code&gt; 추가. 멀티테넌트 SaaS 의 강력한 패턴.&lt;/p&gt;
&lt;p&gt;MySQL 은 RLS 가 없다, 뷰 + 권한으로 흉내 또는 애플리케이션 레벨.&lt;/p&gt;
&lt;h2 id=&quot;트랜잭션과-ddl&quot;&gt;트랜잭션과 DDL&lt;/h2&gt;
&lt;p&gt;dialect 큰 차이.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;PostgreSQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CREATE TABLE&lt;/code&gt; 트랜잭션 안&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;롤백 가능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;묵시적 커밋 (롤백 불가)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ALTER TABLE&lt;/code&gt; 트랜잭션 안&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;롤백 가능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8.0 의 일부 atomic DDL 외엔 묵시적 커밋&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TRUNCATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;롤백 가능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;묵시적 커밋&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;PostgreSQL 마이그레이션 스크립트는 &lt;strong&gt;전부 한 트랜잭션&lt;/strong&gt; 으로 묶을 수 있다, MySQL 은 중간에 멈추면 부분 적용 상태가 남는다.&lt;/p&gt;
&lt;h2 id=&quot;2-phase-commit-분산-트랜잭션&quot;&gt;2-Phase Commit (분산 트랜잭션)&lt;/h2&gt;
&lt;p&gt;여러 노드에 걸친 트랜잭션. PG &lt;code&gt;PREPARE TRANSACTION&lt;/code&gt; / &lt;code&gt;COMMIT PREPARED&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ...;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;PREPARE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TRANSACTION&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;tx1&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 모든 노드가 prepare 성공이면&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PREPARED &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tx1&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 한 노드라도 실패면&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROLLBACK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PREPARED &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tx1&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;운영에선 거의 안 쓴다 (느림, 잠금 길게 유지, 코디네이터 SPOF). Saga 패턴 등 분산 트랜잭션 대안 검토.&lt;/p&gt;
&lt;h2 id=&quot;pandas-와-트랜잭션&quot;&gt;pandas 와 트랜잭션&lt;/h2&gt;
&lt;p&gt;pandas 자체는 트랜잭션 개념이 없다. DB I/O 시 SQLAlchemy 의 connection 컨텍스트가 트랜잭션 역할.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sqlalchemy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; create_engine, text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;engine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; create_engine(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;postgresql://...&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; engine.begin() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; conn:        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 컨텍스트 종료 시 자동 commit, 예외 시 rollback&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    df1.to_sql(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, conn, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;if_exists&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;append&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    df2.to_sql(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, conn, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;if_exists&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;append&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 둘 다 성공해야 commit, 한쪽 실패면 둘 다 rollback&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자세한 [[Pandas read_sql]] 패턴 참고.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-트랜잭션-너무-길게&quot;&gt;1. 트랜잭션 너무 길게&lt;/h3&gt;
&lt;p&gt;대용량 UPDATE 를 한 트랜잭션에 넣으면:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;락 점유 길어짐 → 동시성 저하&lt;/li&gt;
&lt;li&gt;WAL/redo log 부피 증가&lt;/li&gt;
&lt;li&gt;롤백 시간 길어짐 (PG 의 dead tuple 누적)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ 청크 단위 배치, 짧은 트랜잭션 다발.&lt;/p&gt;
&lt;h3 id=&quot;2-select-결과의-즉시성&quot;&gt;2. SELECT 결과의 즉시성&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 다른 트랜잭션이 INSERT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 격리 수준에 따라 100 또는 101&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;REPEATABLE READ 면 같은 트랜잭션 내내 100, READ COMMITTED 면 변할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;3-데드락은-정상&quot;&gt;3. 데드락은 정상&lt;/h3&gt;
&lt;p&gt;운영 DB 에서 데드락은 발생한다, RDBMS 가 감지하고 롤백. 애플리케이션은 &lt;strong&gt;재시도 로직&lt;/strong&gt; 을 가져야 한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; attempt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; engine.begin() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; conn:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            do_work(conn)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        break&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    except&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DeadlockError:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        time.sleep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; **&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; attempt))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-권한-누락&quot;&gt;4. 권한 누락&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ALL TABLES &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SCHEMA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 이후 새로 만든 테이블에는 권한 없음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- → ALTER DEFAULT PRIVILEGES 같이&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;5-grant-option-의-전파&quot;&gt;5. GRANT OPTION 의 전파&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; OPTION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- alice 가 또 다른 사용자에게 GRANT 가능&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 추적 어려워짐, 운영에선 신중히&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;6-최소-권한-원칙&quot;&gt;6. 최소 권한 원칙&lt;/h3&gt;
&lt;p&gt;운영 앱 계정은 보통:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DDL 권한 없음 (CREATE/DROP)&lt;/li&gt;
&lt;li&gt;SELECT/INSERT/UPDATE/DELETE 만, 필요한 테이블에만&lt;/li&gt;
&lt;li&gt;슈퍼유저는 마이그레이션 도구 전용 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DDL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;li&gt;[[Redis]] (대비, NoSQL 의 트랜잭션 모델)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>dcl</category><category>tcl</category><category>transaction</category><category>permission</category><category>security</category><category>database</category><author>koa (김신건)</author></item><item><title>[SQL] DDL</title><link>https://shinkeonkim.com/wiki/sql/sql-ddl/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql-ddl/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;DDL&lt;/strong&gt; (Data Definition Language) 은 &lt;strong&gt;스키마를 정의/변경/제거&lt;/strong&gt; 하는 SQL 의 하위 집합. 대상은 테이블, 인덱스, 뷰, 시퀀스, 스키마, 도메인 등.&lt;/p&gt;
&lt;p&gt;대부분의 DDL 은 &lt;strong&gt;DDL 자체가 한 트랜잭션&lt;/strong&gt; 으로 묶이고 (PostgreSQL 은 트랜잭션 안에서 롤백 가능, MySQL 8.0 의 일부 DDL 은 atomic), 자주 일어나지 않는다. &lt;strong&gt;자주 일어나는 건 DML&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;전체 SQL 체계는 [[SQL]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;핵심-키워드&quot;&gt;핵심 키워드&lt;/h2&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;명령&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CREATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;새 객체 생성&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ALTER&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;기존 객체 수정&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DROP&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;객체 제거&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TRUNCATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;테이블 데이터 전부 제거 (구조 유지, 빠름)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;RENAME&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;이름 변경&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COMMENT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;메타데이터 코멘트 (PG/MySQL 지원)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;create-table-기본&quot;&gt;CREATE TABLE 기본&lt;/h2&gt;
&lt;p&gt;&amp;#x3C;CodeWithOutput
language=“sql”
outputLanguage=“text”
code={`CREATE TABLE users (
id          SERIAL          PRIMARY KEY,
email       VARCHAR(255)    NOT NULL UNIQUE,
name        VARCHAR(50)     NOT NULL,
age         INTEGER         CHECK (age &gt;= 0),
city        VARCHAR(30)     DEFAULT ‘Seoul’,
created_at  TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP
);&lt;/p&gt;
&lt;p&gt;\d users&lt;code&gt;}   output={&lt;/code&gt;             Table “public.users”
Column   |     Type      |   Modifiers
------------+---------------+------------------
id         | integer       | not null PK
email      | varchar(255)  | not null UNIQUE
name       | varchar(50)   | not null
age        | integer       | CHECK (age &gt;= 0)
city       | varchar(30)   | default ‘Seoul’
created_at | timestamp     | not null default now()`}
/&gt;&lt;/p&gt;
&lt;h2 id=&quot;제약조건-constraints&quot;&gt;제약조건 (Constraints)&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;제약&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;예&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NOT NULL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 금지&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;name VARCHAR(50) NOT NULL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;UNIQUE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중복 금지 (단일/복합)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;email VARCHAR(255) UNIQUE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;PRIMARY KEY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NOT NULL + UNIQUE + 테이블당 하나&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;id INTEGER PRIMARY KEY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FOREIGN KEY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;다른 테이블 PK 참조&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;아래 예&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHECK&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;사용자 정의 조건&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CHECK (age &gt;= 0)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DEFAULT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;기본값&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DEFAULT &apos;Seoul&apos;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;복합-키--외래-키&quot;&gt;복합 키 / 외래 키&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order_items&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  order_id   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  product_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  qty        &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CHECK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (qty &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (order_id, product_id),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FOREIGN KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (order_id)   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REFERENCES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders(id)   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON DELETE CASCADE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FOREIGN KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (product_id) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REFERENCES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; products(id) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON DELETE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; RESTRICT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ON DELETE&lt;/code&gt; 옵션:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CASCADE&lt;/code&gt;: 부모 삭제 시 자식도 삭제&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RESTRICT&lt;/code&gt; / &lt;code&gt;NO ACTION&lt;/code&gt;: 자식이 있으면 부모 삭제 거부 (기본)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SET NULL&lt;/code&gt;: 자식의 FK 를 NULL 로&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SET DEFAULT&lt;/code&gt;: 자식의 FK 를 DEFAULT 로&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;명명된-제약&quot;&gt;명명된 제약&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; accounts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  id      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  CONSTRAINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pk_accounts        &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  CONSTRAINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ck_balance_nonneg  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CHECK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (balance &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; accounts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CONSTRAINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ck_balance_nonneg;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이름을 주면 &lt;code&gt;ALTER&lt;/code&gt; 로 핀포인트 변경이 가능하다.&lt;/p&gt;
&lt;h2 id=&quot;자동-증가-pk-dialect-차이&quot;&gt;자동 증가 PK, dialect 차이&lt;/h2&gt;
&lt;p&gt;같은 의미, 문법은 dialect 마다 다르다.&lt;/p&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;p&gt;dialect 별 자세한 비교는 [[PostgreSQL]], [[MySQL]].&lt;/p&gt;
&lt;h2 id=&quot;alter-table&quot;&gt;ALTER TABLE&lt;/h2&gt;
&lt;h3 id=&quot;컬럼-추가삭제수정&quot;&gt;컬럼 추가/삭제/수정&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 컬럼 추가&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ADD&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN phone &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 컬럼 삭제&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN phone;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 타입 변경 (PostgreSQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN age &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TYPE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN age &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TYPE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BIGINT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; age::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 타입 변경 (MySQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;MODIFY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN age &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users CHANGE COLUMN age years &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 이름까지 변경&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 컬럼 이름 변경 (PostgreSQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users RENAME COLUMN age &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; years;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- DEFAULT 변경&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;Busan&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NOT NULL 제약 추가/제거&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;제약조건-추가제거&quot;&gt;제약조건 추가/제거&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ADD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CONSTRAINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uq_users_email &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UNIQUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (email);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ADD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CONSTRAINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fk_users_dept&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FOREIGN KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (dept_id) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REFERENCES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; departments(id);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CONSTRAINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uq_users_email;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;테이블-이름-변경&quot;&gt;테이블 이름 변경&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users RENAME &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; members;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;큰-테이블에서-주의&quot;&gt;큰 테이블에서 주의&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
큰 테이블 (수억 행) 에서 &lt;code&gt;ALTER&lt;/code&gt; 는 테이블 락을 잡고 풀 리라이트가 일어날 수 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL 은 11+ 부터 일부 &lt;code&gt;ADD COLUMN ... DEFAULT&lt;/code&gt; 가 즉시 메타데이터만 변경.&lt;/li&gt;
&lt;li&gt;MySQL 8.0 의 INSTANT 알고리즘: &lt;code&gt;ALGORITHM=INSTANT, LOCK=NONE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;그 외엔 pt-online-schema-change, gh-ost, pg-osc 같은 온라인 마이그레이션 도구 사용.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;drop-table&quot;&gt;DROP TABLE&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; EXISTS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users CASCADE;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 의존 객체 (FK, 뷰) 까지 함께 삭제&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;CASCADE&lt;/code&gt; 는 위험하다. 의도가 명확할 때만.&lt;/p&gt;
&lt;h2 id=&quot;truncate&quot;&gt;TRUNCATE&lt;/h2&gt;
&lt;p&gt;데이터는 다 지우되 테이블 구조는 유지. &lt;code&gt;DELETE&lt;/code&gt; 보다 훨씬 빠르다 (행 단위 로깅 없이 페이지 단위 정리).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TRUNCATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TRUNCATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;RESTART&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IDENTITY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 시퀀스도 리셋 (PG)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TRUNCATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events CASCADE;             &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- FK 참조 자식까지 (PG)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;TRUNCATE&lt;/code&gt; 는 DDL 이라 트랜잭션 안에서 롤백 동작이 dialect 마다 다르다 (PG: OK, MySQL: 묵시적 커밋).&lt;/li&gt;
&lt;li&gt;트리거가 안 걸린다 (행 단위 이벤트가 발생 안 함).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;create-index&quot;&gt;CREATE INDEX&lt;/h2&gt;
&lt;p&gt;조회 성능을 위해. PK/UNIQUE 는 자동 인덱스 생성.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 단일 컬럼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_users_email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users(email);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 복합 (순서 중요, 좌측 prefix 부터 사용 가능)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_orders_user_date&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders(user_id, created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- UNIQUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UNIQUE INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ux_users_email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users(email);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 부분 인덱스 (PostgreSQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_orders_active&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders(user_id) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;active&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 표현식 인덱스&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_users_lower_email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;LOWER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(email));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 동시 생성 (락 최소화, PostgreSQL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; CONCURRENTLY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; idx_huge &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; big_table(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;인덱스 종류&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;용도&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;dialect&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;B-tree (기본)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;등호, 범위, ORDER BY&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모든 RDBMS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Hash&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;등호만&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PG (디스크), MySQL Memory engine&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;GIN&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;다값 (JSONB, 배열, 풀텍스트)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;GiST&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;공간, 범위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;BRIN&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;거대 테이블 + 물리적 클러스터링&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Full-text&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자연어 검색&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PG (&lt;code&gt;tsvector&lt;/code&gt;), MySQL (&lt;code&gt;FULLTEXT&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;인덱스가-효과-없는-경우&quot;&gt;인덱스가 효과 없는 경우&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;컬럼에 함수 적용: &lt;code&gt;WHERE LOWER(name) = &apos;alice&apos;&lt;/code&gt; → 표현식 인덱스 필요&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LIKE &apos;%xxx&apos;&lt;/code&gt; (앞에 와일드카드) → reverse 인덱스 또는 trigram (&lt;code&gt;pg_trgm&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;카디널리티 매우 낮을 때 (성별 1/2) → 옵티마이저가 풀 스캔 선택&lt;/li&gt;
&lt;li&gt;데이터 변환: &lt;code&gt;WHERE CAST(id AS TEXT) = &apos;1&apos;&lt;/code&gt; → 형변환 인덱스 깨짐&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;create-view&quot;&gt;CREATE VIEW&lt;/h2&gt;
&lt;p&gt;쿼리를 이름 붙여 재사용. 뷰는 &lt;strong&gt;저장된 SELECT&lt;/strong&gt;, 데이터를 따로 가지지 않는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; VIEW&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; active_users&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, email&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;active&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; active_users;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 일반 테이블처럼 사용&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;머티리얼라이즈드-뷰-materialized-view&quot;&gt;머티리얼라이즈드 뷰 (Materialized View)&lt;/h3&gt;
&lt;p&gt;결과를 실제로 저장. 빠르지만 갱신이 필요.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MATERIALIZED VIEW user_stats &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cnt, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; avg_sal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;REFRESH MATERIALIZED VIEW user_stats;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 잠금 최소화 (UNIQUE 인덱스 필요)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL 은 기본 머티리얼라이즈드 뷰가 없다, 직접 테이블 + 트리거/스케줄로 구현.&lt;/p&gt;
&lt;h2 id=&quot;create-schema&quot;&gt;CREATE SCHEMA&lt;/h2&gt;
&lt;p&gt;논리 네임스페이스.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SCHEMA&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; analytics&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; analytics&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.events (...);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; search_path &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; analytics, public;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL 은 &lt;code&gt;SCHEMA&lt;/code&gt; 와 &lt;code&gt;DATABASE&lt;/code&gt; 가 동의어. PostgreSQL 은 데이터베이스 안에 여러 스키마.&lt;/p&gt;
&lt;h2 id=&quot;sequence-postgresql&quot;&gt;SEQUENCE (PostgreSQL)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SEQUENCE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order_seq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; START&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; INCREMENT &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders (id, ...) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (NEXTVAL(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;order_seq&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), ...);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CURRVAL(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;order_seq&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SETVAL(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;order_seq&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL 은 시퀀스가 없고 &lt;code&gt;AUTO_INCREMENT&lt;/code&gt; 만 있다.&lt;/p&gt;
&lt;h2 id=&quot;create-trigger&quot;&gt;CREATE TRIGGER&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE OR REPLACE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FUNCTION&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; update_modified&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;RETURNS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TRIGGER &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; $$&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEGIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  NEW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;modified_at&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  RETURN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; NEW;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;END&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$$ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LANGUAGE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; plpgsql;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TRIGGER&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; trg_users_modified&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEFORE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; EACH &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROW&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; EXECUTE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FUNCTION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; update_modified();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TRIGGER&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; trg_users_modified&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEFORE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; EACH &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROW&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NEW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;modified_at&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;pandas-와-sql-ddl&quot;&gt;pandas 와 SQL DDL&lt;/h2&gt;
&lt;p&gt;pandas 는 DDL 이 거의 필요 없다. DataFrame 의 &lt;strong&gt;컬럼 = SQL 의 컬럼&lt;/strong&gt;, &lt;strong&gt;dtype = SQL 의 컬럼 타입&lt;/strong&gt;, 자동으로 추론된다.&lt;/p&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;SQL DDL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;pandas 대응&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CREATE TABLE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.DataFrame({...})&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ALTER TABLE ADD COLUMN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[&apos;new_col&apos;] = ...&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ALTER TABLE DROP COLUMN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.drop(columns=[&apos;col&apos;])&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ALTER COLUMN TYPE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[&apos;col&apos;].astype(...)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DROP TABLE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;del df&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TRUNCATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.drop(df.index)&lt;/code&gt; / &lt;code&gt;df.iloc[0:0]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INDEX&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.set_index(...)&lt;/code&gt; (개념적, 성능적으로 다름)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;DB 에 DataFrame 을 쓸 때는 [[Pandas read_sql]] 의 &lt;code&gt;to_sql(dtype=...)&lt;/code&gt; 로 타입 명시.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-cascade-의-폭발성&quot;&gt;1. CASCADE 의 폭발성&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users CASCADE;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- users 를 참조하는 모든 FK 테이블, 뷰, 함수가 사라질 수 있다&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;운영 환경에선 CASCADE 보다 의존성 파악 후 단계적 DROP.&lt;/p&gt;
&lt;h3 id=&quot;2-큰-테이블의-alter&quot;&gt;2. 큰 테이블의 ALTER&lt;/h3&gt;
&lt;p&gt;수억 행 테이블에 &lt;code&gt;ADD COLUMN ... NOT NULL DEFAULT ...&lt;/code&gt; 는 전부 리라이트. 단계적으로:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;NULL 허용 컬럼 추가&lt;/li&gt;
&lt;li&gt;배치로 백필&lt;/li&gt;
&lt;li&gt;NOT NULL 제약 추가&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;PG 11+ / MySQL 8.0 에선 일부 메타데이터만 바꾸는 INSTANT 가능.&lt;/p&gt;
&lt;h3 id=&quot;3-인덱스-너무-많이&quot;&gt;3. 인덱스 너무 많이&lt;/h3&gt;
&lt;p&gt;INSERT/UPDATE/DELETE 가 모든 인덱스를 갱신. 인덱스 1 개 추가 = 쓰기 비용 증가. 실제 쿼리 plan 보고 결정.&lt;/p&gt;
&lt;h3 id=&quot;4-char-vs-varchar&quot;&gt;4. CHAR vs VARCHAR&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CHAR(N)&lt;/code&gt;: 고정 길이, 짧으면 공백 패딩&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VARCHAR(N)&lt;/code&gt;: 가변 길이, 길이 제한&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TEXT&lt;/code&gt; (PG) / &lt;code&gt;LONGTEXT&lt;/code&gt; (MySQL): 사실상 무제한&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PostgreSQL 은 &lt;code&gt;VARCHAR&lt;/code&gt; 와 &lt;code&gt;TEXT&lt;/code&gt; 의 내부 표현이 같다, 길이 제한 외엔 성능 차이 없음. 일반적으로 &lt;code&gt;TEXT&lt;/code&gt; 권장.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[SQL DCL TCL]]&lt;/li&gt;
&lt;li&gt;[[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>ddl</category><category>schema</category><category>database</category><author>koa (김신건)</author></item><item><title>[SQL] DML</title><link>https://shinkeonkim.com/wiki/sql/sql-dml/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql-dml/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;DML&lt;/strong&gt; (Data Manipulation Language) 은 &lt;strong&gt;데이터 자체를 조회/삽입/수정/삭제&lt;/strong&gt; 하는 SQL 의 하위 집합. 일상 쿼리의 99% 가 여기에 속한다.&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;명령&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;데이터 조회&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INSERT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;새 행 삽입&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;UPDATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;기존 행 수정&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;행 삭제&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;MERGE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;UPSERT (표준), dialect 마다 대안&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;전체 SQL 체계는 [[SQL]] 참고. 스키마 정의는 [[SQL DDL]], 권한·트랜잭션은 [[SQL DCL TCL]].&lt;/p&gt;
&lt;h2 id=&quot;select-전체-골격&quot;&gt;SELECT, 전체 골격&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [DISTINCT] 컬럼1, 컬럼2, 표현식 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alias&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 테이블 [AS] 별칭&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[JOIN ...]                  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 결합&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[WHERE  조건]               &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 행 필터&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[GROUP BY 컬럼]              &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 그룹 분할&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[HAVING 그룹조건]            &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 그룹 필터&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ORDER BY 컬럼 [ASC|DESC]]  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 정렬&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[LIMIT n [OFFSET m]];       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 페이징&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;논리적 실행 순서는 [[SQL]] 의 “쿼리 실행의 논리적 순서” 참고.&lt;/p&gt;
&lt;h2 id=&quot;select-기본-예제&quot;&gt;SELECT 기본 예제&lt;/h2&gt;
&lt;p&gt;&amp;#x3C;CodeWithOutput
language=“sql”
outputLanguage=“text”
code={`— 전체
SELECT * FROM users;&lt;/p&gt;
&lt;p&gt;— 컬럼 선택 + 별칭
SELECT id, name AS user_name, salary * 12 AS yearly
FROM users;&lt;/p&gt;
&lt;p&gt;— 필터 + 정렬 + 페이징
SELECT name, salary
FROM users
WHERE city = ‘Seoul’ AND salary &gt;= 3000
ORDER BY salary DESC
LIMIT 5;&lt;/p&gt;
&lt;p&gt;— 중복 제거
SELECT DISTINCT city FROM users;&lt;code&gt;}   output={&lt;/code&gt;— users 전체
id |  name   | city  | salary
----+---------+-------+--------
1 | Alice   | Seoul |   3000
2 | Bob     | Busan |   4000
3 | Charlie | Seoul |   3500&lt;/p&gt;
&lt;p&gt;— Seoul + 3000 이상, 내림차순
name   | salary
---------+--------
Charlie |   3500
Alice   |   3000`}
/&gt;&lt;/p&gt;
&lt;h2 id=&quot;where-의-연산자&quot;&gt;WHERE 의 연산자&lt;/h2&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;연산&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;=&lt;/code&gt;, &lt;code&gt;&amp;#x3C;&gt;&lt;/code&gt; (&lt;code&gt;!=&lt;/code&gt;), &lt;code&gt;&amp;#x3C;&lt;/code&gt;, &lt;code&gt;&amp;#x3C;=&lt;/code&gt;, &lt;code&gt;&gt;&lt;/code&gt;, &lt;code&gt;&gt;=&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;비교&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, &lt;code&gt;NOT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;부울&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BETWEEN a AND b&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;&gt;= a AND &amp;#x3C;= b&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;IN (...)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;집합 멤버&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIKE&lt;/code&gt; / &lt;code&gt;ILIKE&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;패턴 (&lt;code&gt;%&lt;/code&gt;, &lt;code&gt;_&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;IS NULL&lt;/code&gt; / &lt;code&gt;IS NOT NULL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 검사&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;EXISTS (subquery)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;결과 존재 여부&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
NULL 비교는 &lt;code&gt;=&lt;/code&gt; 가 안 통한다. &lt;code&gt;WHERE col = NULL&lt;/code&gt; 은 항상 거짓. &lt;code&gt;WHERE col IS NULL&lt;/code&gt; 을 써야 한다. [[SQL]] 의 “NULL 의 3-값 논리” 참고.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;like-패턴&quot;&gt;LIKE 패턴&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIKE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;A%&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;      -- A 로 시작&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIKE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;%son&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- son 으로 끝&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIKE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;_lice&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   -- 한 글자 + lice&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIKE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;%50\\%%&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ESCAPE &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;\\&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   -- 리터럴 % 검색&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;select-표현식&quot;&gt;SELECT 표현식&lt;/h2&gt;
&lt;p&gt;산술, 문자열, 날짜 함수, &lt;code&gt;CASE WHEN&lt;/code&gt;. 자세한 타입별 연산은 [[SQL Data Types]] 참고.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  salary,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;               AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; yearly,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  CASE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    WHEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; THEN&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;high&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    WHEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; THEN&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;mid&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ELSE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                     &apos;low&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  END&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tier,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  EXTRACT(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;YEAR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; join_year&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;order-by-의-디테일&quot;&gt;ORDER BY 의 디테일&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                          -- 단일 컬럼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ASC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                -- 여러 컬럼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DESC&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                               -- SELECT 절 N 번째 컬럼 (가독성 나쁨)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULLS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LAST&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;               -- NULL 위치 지정 (PG 표준)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;dialect 차이:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL: 기본 &lt;code&gt;NULLS LAST&lt;/code&gt; for DESC, &lt;code&gt;NULLS FIRST&lt;/code&gt; for ASC. 명시 가능.&lt;/li&gt;
&lt;li&gt;MySQL: 기본 &lt;code&gt;NULLS FIRST&lt;/code&gt;. &lt;code&gt;NULLS LAST&lt;/code&gt; 미지원, &lt;code&gt;ORDER BY col IS NULL, col&lt;/code&gt; 우회.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;limit--offset-의-함정&quot;&gt;LIMIT / OFFSET 의 함정&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; OFFSET &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;OFFSET&lt;/code&gt; 은 &lt;strong&gt;스킵하기 위해 그 행들을 다 읽는다&lt;/strong&gt;. 깊은 페이지에서 매우 느림.&lt;/p&gt;
&lt;p&gt;해법: &lt;strong&gt;Keyset Pagination (cursor)&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 첫 페이지&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 다음 페이지: 마지막 id 를 cursor 로&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 12345&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;서브쿼리&quot;&gt;서브쿼리&lt;/h2&gt;
&lt;h3 id=&quot;스칼라-서브쿼리&quot;&gt;스칼라 서브쿼리&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  salary,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; overall_avg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;in--exists&quot;&gt;IN / EXISTS&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; amount &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; EXISTS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;옵티마이저는 보통 &lt;code&gt;EXISTS&lt;/code&gt; 가 더 빠르다 (첫 매칭에서 짧게 끊음). &lt;code&gt;IN&lt;/code&gt; 은 결과 집합 전체를 만든다.&lt;/p&gt;
&lt;h3 id=&quot;상관-서브쿼리-correlated&quot;&gt;상관 서브쿼리 (Correlated)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MAX&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(amount) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; max_order&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;외부 쿼리의 행마다 내부 쿼리가 실행, 비용 큼. JOIN 으로 풀 수 있는지 검토.&lt;/p&gt;
&lt;h3 id=&quot;cte-common-table-expression&quot;&gt;CTE (Common Table Expression)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;WITH&lt;/code&gt; 절로 이름 붙인 임시 결과셋. 가독성 + 재사용.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; high_paid &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;their_orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; high_paid u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SUM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(amount) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; total&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; their_orders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 12+, MySQL 8+ 에서 잘 동작. 옵티마이저가 inline 화 (PG 12+) 또는 머티리얼라이즈 (PG 11-).&lt;/p&gt;
&lt;h3 id=&quot;재귀-cte&quot;&gt;재귀 CTE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; RECURSIVE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; category_tree &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, parent_id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; depth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; categories&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parent_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  UNION ALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;parent_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;depth&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; categories c&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; category_tree ct &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;parent_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; category_tree &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; depth, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;조직도, 카테고리, BFS/DFS 트리 순회에.&lt;/p&gt;
&lt;h2 id=&quot;insert&quot;&gt;INSERT&lt;/h2&gt;
&lt;h3 id=&quot;단일다중-행&quot;&gt;단일/다중 행&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, city, salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, city, salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Bob&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,     &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Busan&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Charlie&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3500&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;insert--select&quot;&gt;INSERT … SELECT&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users_backup (id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, city, salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, city, salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;2024-01-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;returning-postgresql&quot;&gt;RETURNING (PostgreSQL)&lt;/h3&gt;
&lt;p&gt;INSERT/UPDATE/DELETE 의 결과를 즉시 반환. 자동 생성된 PK 받기에 좋다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, city, salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Diana&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3200&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;RETURNING id, created_at;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL 은 &lt;code&gt;RETURNING&lt;/code&gt; 미지원. &lt;code&gt;LAST_INSERT_ID()&lt;/code&gt; 함수로 마지막 PK 만 조회 가능. MariaDB 는 지원.&lt;/p&gt;
&lt;h2 id=&quot;update&quot;&gt;UPDATE&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    updated_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;다른-테이블-참조해서-update&quot;&gt;다른 테이블 참조해서 UPDATE&lt;/h3&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;h3 id=&quot;where-없는-update-의-무서움&quot;&gt;WHERE 없는 UPDATE 의 무서움&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ⚠️ 전체 행 갱신!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;운영 DB 에선 항상 &lt;code&gt;BEGIN&lt;/code&gt; → &lt;code&gt;SELECT&lt;/code&gt; 로 검증 → &lt;code&gt;UPDATE&lt;/code&gt; → &lt;code&gt;COMMIT&lt;/code&gt; 의 흐름. [[SQL DCL TCL]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;delete&quot;&gt;DELETE&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DELETE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DELETE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;2020-01-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;다른-테이블-참조해서-delete&quot;&gt;다른 테이블 참조해서 DELETE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PostgreSQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DELETE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blacklist b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DELETE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; u &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blacklist b &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;delete-vs-truncate&quot;&gt;DELETE vs TRUNCATE&lt;/h3&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;DELETE&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;TRUNCATE&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;구분&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DML&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DDL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;WHERE&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✗ (전체만)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;트리거&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;동작&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;동작 안 함&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;시퀀스 리셋&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✗&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;옵션 (PG)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;속도&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;행 단위, 느림&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;페이지 단위, 빠름&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FK&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RESTRICT 가능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CASCADE 필요&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;트랜잭션 롤백&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;dialect 따라&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;upsert-dialect-차이&quot;&gt;UPSERT, dialect 차이&lt;/h2&gt;
&lt;p&gt;같은 키가 있으면 UPDATE, 없으면 INSERT.&lt;/p&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;h2 id=&quot;pandas-와-dml-의-대응&quot;&gt;pandas 와 DML 의 대응&lt;/h2&gt;





























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;SQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;pandas&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT * FROM t&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT col FROM t&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[[&apos;col&apos;]]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT * FROM t WHERE c &gt; 10&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[df[&apos;c&apos;] &gt; 10]&lt;/code&gt; ([[Pandas Boolean Indexing]])&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ORDER BY c DESC&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.sort_values(&apos;c&apos;, ascending=False)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIMIT 10&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.head(10)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DISTINCT c&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[&apos;c&apos;].drop_duplicates()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;WHERE c IN (...)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[df[&apos;c&apos;].isin([...])]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;WHERE c LIKE &apos;%x%&apos;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[df[&apos;c&apos;].str.contains(&apos;x&apos;, na=False)]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CASE WHEN ...&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;np.where(...)&lt;/code&gt;, &lt;code&gt;df[&apos;c&apos;].map(...)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INSERT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.concat([df, new_rows])&lt;/code&gt; 또는 &lt;code&gt;df.loc[len(df)] = ...&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;UPDATE ... SET c = ... WHERE ...&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.loc[mask, &apos;c&apos;] = ...&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DELETE ... WHERE ...&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df = df[~mask]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;WITH cte AS (...)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중간 DataFrame 변수&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt; 가 mask 한 줄로 처리되는 게 pandas 의 강점, 거꾸로 INSERT 의 효율은 SQL 이 압도적. 적재적소.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-select--를-운영-코드에&quot;&gt;1. SELECT * 를 운영 코드에&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;스키마 변경 시 깨짐&lt;/li&gt;
&lt;li&gt;네트워크 비용&lt;/li&gt;
&lt;li&gt;인덱스 only-scan 못 씀&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;명시적으로 컬럼 나열.&lt;/p&gt;
&lt;h3 id=&quot;2-null-의-전파&quot;&gt;2. NULL 의 전파&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; col_a &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; col_b &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 어느 한쪽이 NULL 이면 결과 NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COALESCE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(col_a, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COALESCE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(col_b, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 0 으로 대체&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-묵시적-형변환&quot;&gt;3. 묵시적 형변환&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- id 가 INTEGER 면 문자→숫자 변환, 인덱스 쓸 수 있음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; CAST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TEXT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   -- 컬럼에 함수 적용, 인덱스 깨짐&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;문자열 칼럼에 숫자를 넣으면 PG 는 에러, MySQL 은 묵시적 변환 (조용한 버그의 원천).&lt;/p&gt;
&lt;h3 id=&quot;4-where-와-having-혼동&quot;&gt;4. WHERE 와 HAVING 혼동&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ❌ 에러: WHERE 는 집계 결과 못 봄&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ✓ HAVING 에 써야 함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;HAVING&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자세한 GROUP BY 의 의미와 동작은 [[SQL GROUP BY]].&lt;/p&gt;
&lt;h3 id=&quot;5-페이지-깊은-offset&quot;&gt;5. 페이지 깊은 OFFSET&lt;/h3&gt;
&lt;p&gt;운영 환경에서 무한 스크롤은 keyset pagination 으로.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DDL]]&lt;/li&gt;
&lt;li&gt;[[SQL JOIN]]&lt;/li&gt;
&lt;li&gt;[[SQL GROUP BY]]&lt;/li&gt;
&lt;li&gt;[[SQL DCL TCL]]&lt;/li&gt;
&lt;li&gt;[[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas Boolean Indexing]]&lt;/li&gt;
&lt;li&gt;[[Pandas groupby]]&lt;/li&gt;
&lt;li&gt;[[Pandas merge]]&lt;/li&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>dml</category><category>select</category><category>insert</category><category>update</category><category>delete</category><category>database</category><author>koa (김신건)</author></item><item><title>[SQL] GROUP BY</title><link>https://shinkeonkim.com/wiki/sql/sql-group-by/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql-group-by/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/strong&gt; 는 데이터를 키별로 그룹으로 나누고 각 그룹에 &lt;strong&gt;집계 함수 (aggregate)&lt;/strong&gt; 를 적용해 그룹당 한 행으로 줄이는 연산. SQL 의 split-apply-combine.&lt;/p&gt;
&lt;p&gt;[[Pandas groupby]] 와 1:1 대응. 시각화도 동일하게 사용한다.&lt;/p&gt;
&lt;h2 id=&quot;시각화&quot;&gt;시각화&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;기본-골격&quot;&gt;기본 골격&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 그룹키, 집계함수(컬럼)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 테이블&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[WHERE 조건]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 그룹키&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[HAVING 그룹조건]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ORDER BY ...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행 순서는 [[SQL]] 의 “쿼리 실행의 논리적 순서” 참고. &lt;strong&gt;&lt;code&gt;WHERE&lt;/code&gt; → &lt;code&gt;GROUP BY&lt;/code&gt; → &lt;code&gt;HAVING&lt;/code&gt; → &lt;code&gt;SELECT&lt;/code&gt;&lt;/strong&gt; 임을 기억.&lt;/p&gt;
&lt;h2 id=&quot;기본-예제&quot;&gt;기본 예제&lt;/h2&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;p&gt;&lt;code&gt;city&lt;/code&gt; 가 같은 행끼리 모이고 각 그룹에서 &lt;code&gt;AVG(salary)&lt;/code&gt;, &lt;code&gt;COUNT(*)&lt;/code&gt; 가 계산된다.&lt;/p&gt;
&lt;h2 id=&quot;집계-함수-aggregate-functions&quot;&gt;집계 함수 (Aggregate Functions)&lt;/h2&gt;
&lt;p&gt;표준 SQL 의 핵심 집계.&lt;/p&gt;




























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;함수&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;NULL 처리&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COUNT(*)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;행 수 (NULL 포함)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 행도 셈&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COUNT(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;non-NULL 행 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 제외&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COUNT(DISTINCT col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;고유값 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 제외&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SUM(col)&lt;/code&gt;, &lt;code&gt;AVG(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;합, 평균&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 무시&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;MIN(col)&lt;/code&gt;, &lt;code&gt;MAX(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;극값&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 무시&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;STDDEV(col)&lt;/code&gt;, &lt;code&gt;VARIANCE(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준편차, 분산&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 무시&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOL_AND&lt;/code&gt;, &lt;code&gt;BOOL_OR&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모두 참, 하나라도 참&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 무시&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;STRING_AGG(col, sep)&lt;/code&gt; (PG) / &lt;code&gt;GROUP_CONCAT(col SEPARATOR sep)&lt;/code&gt; (MySQL)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;문자열 합&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 무시&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ARRAY_AGG(col)&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배열 합&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NULL 포함&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON_AGG(col)&lt;/code&gt; (PG) / &lt;code&gt;JSON_ARRAYAGG(col)&lt;/code&gt; (MySQL 8+)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JSON 배열&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;dialect 따라&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;null-의-묵시적-무시-함정&quot;&gt;NULL 의 묵시적 무시 함정&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- score 컬럼에 NULL 이 섞여 있을 때&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)        &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; total,      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL 포함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(score)    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; scored,     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL 제외&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(score)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; avg_score,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL 제외하고 평균&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  SUM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(score) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; my_avg  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL 도 0 으로 친 평균 (보통 의도와 다름)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exams;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;code&gt;AVG&lt;/code&gt; 는 분모가 non-NULL 개수. 결측치가 많을 때 의미가 변한다. 의도하면 &lt;code&gt;COALESCE(score, 0)&lt;/code&gt; 으로 명시.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;having-집계-조건&quot;&gt;HAVING, 집계 조건&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; 는 집계 전, &lt;code&gt;HAVING&lt;/code&gt; 은 집계 후.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;CodeWithOutput
language=“sql”
outputLanguage=“text”
code={`— ❌ WHERE 에 집계 함수 (에러)
SELECT city, COUNT(&lt;em&gt;) FROM users
WHERE COUNT(&lt;/em&gt;) &gt; 2
GROUP BY city;&lt;/p&gt;
&lt;p&gt;— ✓ HAVING 이 정답
SELECT city, COUNT(&lt;em&gt;) AS cnt
FROM users
GROUP BY city
HAVING COUNT(&lt;/em&gt;) &gt; 2;&lt;code&gt;}   output={&lt;/code&gt;— 첫 번째: ERROR: aggregate functions are not allowed in WHERE&lt;/p&gt;
&lt;p&gt;— 두 번째:
city   | cnt
---------+-----
Seoul   |   3`}
/&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- WHERE + HAVING 같이 쓸 수도&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; active &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TRUE          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 그룹 전, active 사용자만&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;HAVING&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 그룹 후, 평균이 큰 city&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;여러-컬럼-그룹&quot;&gt;여러 컬럼 그룹&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, dept, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; avg_sal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, dept;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;city&lt;/th&gt;&lt;th&gt;dept&lt;/th&gt;&lt;th&gt;avg_sal&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Seoul&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;3250.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Seoul&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;5000.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Busan&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;4000.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Busan&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;4500.0&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;(city, dept) 의 모든 고유 조합당 한 행.&lt;/p&gt;
&lt;h2 id=&quot;rollup--cube--grouping-sets&quot;&gt;ROLLUP / CUBE / GROUPING SETS&lt;/h2&gt;
&lt;p&gt;여러 수준의 소계/총계를 한 쿼리로.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, dept, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SUM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ROLLUP&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (city, dept);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;city&lt;/th&gt;&lt;th&gt;dept&lt;/th&gt;&lt;th&gt;sum&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Seoul&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;6500&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Seoul&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;5000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Seoul&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;11500 (city 소계)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Busan&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;4000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Busan&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;4500&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Busan&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;8500&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;20000 (총계)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;구문&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ROLLUP (a, b)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;(a, b), (a), ()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CUBE (a, b)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;(a, b), (a), (b), ()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GROUPING SETS ((a, b), (a))&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;사용자 정의&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;PG/MySQL 8 모두 지원. 분석/OLAP 보고서에 빠르고 깔끔.&lt;/p&gt;
&lt;h2 id=&quot;group-by-의-select-제약&quot;&gt;GROUP BY 의 SELECT 제약&lt;/h2&gt;
&lt;p&gt;표준 SQL: &lt;code&gt;SELECT&lt;/code&gt; 절에 나오는 비집계 컬럼은 &lt;strong&gt;모두 &lt;code&gt;GROUP BY&lt;/code&gt; 에 있어야 한다&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ❌ 표준 위반: name 이 GROUP BY 에 없음&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;dialect 차이:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL: 엄격, 에러.&lt;/li&gt;
&lt;li&gt;MySQL: 기본은 허용 (조용히 임의의 값). &lt;code&gt;sql_mode=ONLY_FULL_GROUP_BY&lt;/code&gt; 면 엄격. &lt;strong&gt;MySQL 5.7+ 부터 ONLY_FULL_GROUP_BY 가 기본&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;해법: 명시적 집계 또는 GROUP BY 에 포함.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MAX&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 명시적 집계&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 그룹키 추가&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;distinct-vs-group-by&quot;&gt;DISTINCT vs GROUP BY&lt;/h2&gt;
&lt;p&gt;같은 결과지만 의미가 다르다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT DISTINCT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, dept &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, dept           &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, dept;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;둘 다 같은 결과셋. 옵티마이저는 보통 같은 plan 으로 처리. &lt;code&gt;GROUP BY&lt;/code&gt; 는 집계가 따라올 때, &lt;code&gt;DISTINCT&lt;/code&gt; 는 단순 중복 제거 의도일 때.&lt;/p&gt;
&lt;h2 id=&quot;윈도-함수-window-functions&quot;&gt;윈도 함수 (Window Functions)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;그룹별 집계를 행 단위로 보존하며&lt;/strong&gt; 계산. &lt;code&gt;GROUP BY&lt;/code&gt; 가 그룹당 한 행, 윈도는 모든 행 유지.&lt;/p&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;h3 id=&quot;윈도-함수-종류&quot;&gt;윈도 함수 종류&lt;/h3&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;카테고리&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;함수&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;집계&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SUM&lt;/code&gt;, &lt;code&gt;AVG&lt;/code&gt;, &lt;code&gt;COUNT&lt;/code&gt;, …&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;OVER&lt;/code&gt; 가 있으면 윈도&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;순위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ROW_NUMBER()&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1, 2, 3, … (동률 무시)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;순위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;RANK()&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1, 2, 2, 4 (동률 공유, 다음 점프)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;순위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DENSE_RANK()&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1, 2, 2, 3 (동률 공유, 점프 없음)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;순위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NTILE(n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;n 분위수&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;오프셋&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LAG(col, n)&lt;/code&gt;, &lt;code&gt;LEAD(col, n)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;n 행 전/후 값&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;경계&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FIRST_VALUE&lt;/code&gt;, &lt;code&gt;LAST_VALUE&lt;/code&gt;, &lt;code&gt;NTH_VALUE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;윈도 내 위치 값&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;통계&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;PERCENT_RANK&lt;/code&gt;, &lt;code&gt;CUME_DIST&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;누적 분포&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;윈도-프레임-frame&quot;&gt;윈도 프레임 (Frame)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;OVER (PARTITION BY ... ORDER BY ... ROWS/RANGE BETWEEN ... AND ...)&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 7 일 이동평균&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  amount,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(amount) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; date&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ROWS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BETWEEN&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRECEDING&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CURRENT &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROW&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ma7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; daily_sales;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 누적합&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  amount,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  SUM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(amount) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cumsum&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; daily_sales;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[[Pandas rolling]] / [[Pandas expanding]] 와 같은 개념.&lt;/p&gt;
&lt;h2 id=&quot;pandas-와-group-by&quot;&gt;pandas 와 GROUP BY&lt;/h2&gt;
&lt;h3 id=&quot;기본-대응&quot;&gt;기본 대응&lt;/h3&gt;

























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;SQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;pandas&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GROUP BY city&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.groupby(&apos;city&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;AVG(salary)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;.mean()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COUNT(*)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;.size()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COUNT(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;.count()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;COUNT(DISTINCT col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;.nunique()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SUM(col)&lt;/code&gt;, &lt;code&gt;MIN(col)&lt;/code&gt;, &lt;code&gt;MAX(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;.sum()&lt;/code&gt;, &lt;code&gt;.min()&lt;/code&gt;, &lt;code&gt;.max()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;HAVING ...&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;.filter(lambda g: ...)&lt;/code&gt; 또는 &lt;code&gt;.agg(...).query(...)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GROUP BY a, b&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.groupby([&apos;a&apos;, &apos;b&apos;])&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ROLLUP/CUBE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;crosstab(margins=True)&lt;/code&gt;, [[Pandas pivot_table]] &lt;code&gt;margins=True&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ROW_NUMBER() OVER (PARTITION BY x ORDER BY y)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.sort_values(&apos;y&apos;).groupby(&apos;x&apos;).cumcount() + 1&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LAG(col)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.groupby(&apos;x&apos;)[&apos;col&apos;].shift(1)&lt;/code&gt; ([[Pandas shift]])&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;AVG(...) OVER (ROWS 6 PRECEDING)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.rolling(7).mean()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;예시-비교&quot;&gt;예시 비교&lt;/h3&gt;
&lt;p&gt;&amp;#x3C;CodeWithOutput
variants={[
{ language: ‘sql’, label: ‘SQL’, code: &lt;code&gt;SELECT   city,   COUNT(*) AS cnt,   AVG(salary)       AS avg_sal,   COUNT(DISTINCT dept) AS dept_cnt FROM users WHERE active = TRUE GROUP BY city HAVING COUNT(*) &gt;= 2 ORDER BY avg_sal DESC;&lt;/code&gt; },
{ language: ‘python’, label: ‘pandas’, code: &lt;code&gt;result = (     df[df[&apos;active&apos;]]     .groupby(&apos;city&apos;)     .agg(         cnt=(&apos;city&apos;, &apos;size&apos;),         avg_sal=(&apos;salary&apos;, &apos;mean&apos;),         dept_cnt=(&apos;dept&apos;, &apos;nunique&apos;),     )     .query(&apos;cnt &gt;= 2&apos;)     .sort_values(&apos;avg_sal&apos;, ascending=False) )&lt;/code&gt; },
]}
outputLabel=“결과”
output={&lt;code&gt;-- 양쪽 모두 동일한 의미와 결과 -- city 별로 active 사용자만 집계, 2명 이상인 도시만, 평균 급여 내림차순&lt;/code&gt;}
/&gt;&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-where-와-having-헷갈림&quot;&gt;1. WHERE 와 HAVING 헷갈림&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- WHERE 는 집계 전, HAVING 은 집계 후&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;       -- 개별 행 필터&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;HAVING&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  -- 그룹 필터&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-count-vs-countcol&quot;&gt;2. COUNT(*) vs COUNT(col)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 행 수&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- non-NULL 행 수, 종종 의도와 다름&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(active) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- active 가 NULL 인 행은 안 셈&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-count-와-left-join&quot;&gt;3. COUNT 와 LEFT JOIN&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 주문 없는 사용자 cnt 가 0 이 아니라 1 이 나오는 함정&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order_count&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- COUNT(*) 는 LEFT JOIN 의 NULL 행도 셈 (1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ✓ COUNT(o.id) 가 정답 (NULL 무시)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order_count&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-group-by-후-정렬-컬럼&quot;&gt;4. GROUP BY 후 정렬 컬럼&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- SELECT 의 별칭을 ORDER BY 에 쓸 수 있는지는 dialect 마다 다름&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; avg_sal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; avg_sal &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG/MySQL 모두 OK&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;5-큰-카디널리티-group-by&quot;&gt;5. 큰 카디널리티 GROUP BY&lt;/h3&gt;
&lt;p&gt;수억 행 × 그룹키가 수백만 → hash table 폭발. &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; 로 &lt;code&gt;work_mem&lt;/code&gt; (PG) 또는 &lt;code&gt;tmp_table_size&lt;/code&gt; (MySQL) 확인. [[External Merge Sort]] / Grace Hash 처럼 디스크 spill 발생.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[SQL JOIN]]&lt;/li&gt;
&lt;li&gt;[[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas groupby]]&lt;/li&gt;
&lt;li&gt;[[Pandas agg]]&lt;/li&gt;
&lt;li&gt;[[Pandas pivot_table]]&lt;/li&gt;
&lt;li&gt;[[Pandas shift]]&lt;/li&gt;
&lt;li&gt;[[Pandas rolling]]&lt;/li&gt;
&lt;li&gt;[[External Merge Sort]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>group-by</category><category>aggregate</category><category>having</category><category>window-function</category><category>database</category><author>koa (김신건)</author></item><item><title>[SQL] JOIN</title><link>https://shinkeonkim.com/wiki/sql/sql-join/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql-join/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;JOIN&lt;/strong&gt; 은 두 개 이상의 테이블을 &lt;strong&gt;공통 컬럼 (보통 키)&lt;/strong&gt; 으로 결합해 한 결과셋으로 만드는 연산. SQL 의 관계 모델 핵심.&lt;/p&gt;
&lt;p&gt;종류는 5 가지: &lt;code&gt;INNER&lt;/code&gt;, &lt;code&gt;LEFT&lt;/code&gt;, &lt;code&gt;RIGHT&lt;/code&gt;, &lt;code&gt;FULL OUTER&lt;/code&gt;, &lt;code&gt;CROSS&lt;/code&gt;. 같은 테이블끼리 결합하는 &lt;code&gt;SELF JOIN&lt;/code&gt; 은 별도 종류가 아니라 같은 테이블을 두 번 참조하는 패턴.&lt;/p&gt;
&lt;p&gt;pandas 의 [[Pandas merge]] 가 완전 대응되는 개념. 시각화는 동일하게 사용한다.&lt;/p&gt;
&lt;h2 id=&quot;시각화&quot;&gt;시각화&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;4-가지-메인-join-타입&quot;&gt;4 가지 메인 JOIN 타입&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;how&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;SQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;결과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;내부&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;양쪽 매칭만&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;좌측 외부&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LEFT [OUTER] JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;왼쪽 전부 + 매칭, 없으면 NULL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;우측 외부&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;RIGHT [OUTER] JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;오른쪽 전부 + 매칭&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;완전 외부&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FULL [OUTER] JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;양쪽 합집합, 없으면 NULL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;데카르트곱&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CROSS JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모든 조합 (m × n)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;예제-데이터&quot;&gt;예제 데이터&lt;/h2&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;h2 id=&quot;inner-join&quot;&gt;INNER JOIN&lt;/h2&gt;
&lt;p&gt;양쪽 모두 매칭되는 행만.&lt;/p&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;p&gt;Alice (2 주문), Bob (1 주문) 만. Charlie 는 주문 없음, orders.user_id=4 는 users 에 없음.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;INNER&lt;/code&gt; 키워드는 생략 가능, &lt;code&gt;JOIN&lt;/code&gt; 만 쓰면 &lt;code&gt;INNER JOIN&lt;/code&gt;. 명시 권장.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;left-join&quot;&gt;LEFT JOIN&lt;/h2&gt;
&lt;p&gt;왼쪽 테이블의 모든 행 + 오른쪽 매칭. 없으면 오른쪽 컬럼은 &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;p&gt;Charlie 도 나타난다, &lt;code&gt;amount&lt;/code&gt; 는 &lt;code&gt;NULL&lt;/code&gt;. &lt;strong&gt;“users 전부 + 그들의 주문”&lt;/strong&gt; 같은 질문에 적합.&lt;/p&gt;
&lt;h3 id=&quot;left-join--is-null--안티-조인&quot;&gt;LEFT JOIN + IS NULL = 안티 조인&lt;/h3&gt;
&lt;p&gt;“오른쪽에 없는 왼쪽 행” 찾기.&lt;/p&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;p&gt;&lt;code&gt;NOT EXISTS&lt;/code&gt; / &lt;code&gt;NOT IN&lt;/code&gt; 으로 같은 결과를 낼 수 있지만, 옵티마이저가 가장 효율적인 plan 을 짜기에 유리한 건 dialect/통계에 따라 다르다.&lt;/p&gt;
&lt;h2 id=&quot;right-join&quot;&gt;RIGHT JOIN&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt; 의 좌우 반전.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;RIGHT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;id&lt;/th&gt;&lt;th&gt;name&lt;/th&gt;&lt;th&gt;amount&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Alice&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Alice&lt;/td&gt;&lt;td&gt;200&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;Bob&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;50&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;orders 의 user_id=4 행도 나타난다 (사용자 없음, NULL).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;실무에선 &lt;code&gt;RIGHT JOIN&lt;/code&gt; 보다 &lt;code&gt;FROM&lt;/code&gt; 의 테이블 순서를 바꾸고 &lt;code&gt;LEFT JOIN&lt;/code&gt; 쓰는 게 가독성 좋다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;full-outer-join&quot;&gt;FULL OUTER JOIN&lt;/h2&gt;
&lt;p&gt;양쪽 모두 보존, 매칭 안 되면 반대편이 NULL.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FULL OUTER JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;u.id&lt;/th&gt;&lt;th&gt;name&lt;/th&gt;&lt;th&gt;amount&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Alice&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Alice&lt;/td&gt;&lt;td&gt;200&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;Bob&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;Charlie&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;NULL&lt;/td&gt;&lt;td&gt;50&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
MySQL 은 &lt;code&gt;FULL OUTER JOIN&lt;/code&gt; 을 직접 지원하지 않는다. &lt;code&gt;LEFT JOIN UNION RIGHT JOIN&lt;/code&gt; 으로 흉내.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UNION&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;RIGHT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;cross-join&quot;&gt;CROSS JOIN&lt;/h2&gt;
&lt;p&gt;모든 조합 (데카르트곱). 행 수 = m × n.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;color&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CROSS JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; colors c;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ON&lt;/code&gt; 절이 없다. 보통 의도된 사용은 작은 룩업 테이블 확장, 카탈로그 매트릭스 생성.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
큰 두 테이블 사이의 &lt;code&gt;CROSS JOIN&lt;/code&gt; 은 즉시 메모리/디스크를 폭발시킨다. 1만 × 1만 = 1억 행.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;암시적 cross join (구식):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;color&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u, colors c;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 같은 결과&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; 절을 깜빡하면 의도치 않은 cross join 이 된다, 명시적 &lt;code&gt;CROSS JOIN&lt;/code&gt; 이 안전.&lt;/p&gt;
&lt;h2 id=&quot;self-join&quot;&gt;SELF JOIN&lt;/h2&gt;
&lt;p&gt;같은 테이블을 두 번 참조. 보통 부모-자식 관계, 동일 도메인 비교.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 매니저-부하 관계&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employee, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; manager&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employees e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employees m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;manager_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; m&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 같은 city 의 다른 사람&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; roommate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;city&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;city&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 중복 쌍 제거 (id 순으로만)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;테이블 별칭이 필수.&lt;/p&gt;
&lt;h2 id=&quot;on-vs-using-vs-natural-join&quot;&gt;ON vs USING vs NATURAL JOIN&lt;/h2&gt;
&lt;h3 id=&quot;on&quot;&gt;ON&lt;/h3&gt;
&lt;p&gt;가장 일반적, 가장 명시적.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;active&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;using-양쪽-컬럼-이름-같을-때&quot;&gt;USING (양쪽 컬럼 이름 같을 때)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (user_id)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ON 절의 짧은 버전, 결과 컬럼이 한 번만 나옴&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;natural-join&quot;&gt;NATURAL JOIN&lt;/h3&gt;
&lt;p&gt;같은 이름의 모든 컬럼을 자동으로 매칭. 위험하다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NATURAL JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- created_at, id 같은 우연히 겹친 컬럼까지 join 키가 됨&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;스키마가 바뀌면 의미가 조용히 바뀐다. &lt;strong&gt;거의 항상 명시적 &lt;code&gt;ON&lt;/code&gt; 권장.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;여러-테이블-join&quot;&gt;여러 테이블 JOIN&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; product&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders   o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order_items oi &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; oi&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;order_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; products p  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;         =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; oi&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;product_id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;city&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;옵티마이저가 join 순서를 선택. 통계 가 정확하면 효율적, 아니면 nested-loop 폭발.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;join-알고리즘-간단&quot;&gt;JOIN 알고리즘 (간단)&lt;/h2&gt;
&lt;p&gt;옵티마이저가 선택하는 물리 알고리즘 3 가지.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;알고리즘&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;조건&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;비용&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Nested Loop&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;한쪽이 작거나 인덱스 있는 경우&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;O(n × m), 인덱스 시 O(n log m)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Hash Join&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;등호 join, 한쪽이 메모리에 들어감&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;O(n + m), build/probe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Sort-Merge&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;양쪽 정렬됨 또는 정렬 비용 감당 가능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;O(n log n + m log m)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;대용량 hash join 은 [[External Merge Sort]] 와 비슷하게 메모리 부족 시 디스크로 spill 한다 (Grace Hash Join). PG/MySQL &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; 로 확인.&lt;/p&gt;
&lt;h2 id=&quot;pandas-와-sql-join&quot;&gt;pandas 와 SQL JOIN&lt;/h2&gt;
&lt;p&gt;[[Pandas merge]] 와 1:1 대응.&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;SQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;pandas&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;inner&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;left&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;right&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FULL OUTER JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;outer&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CROSS JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;cross&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ON a.x = b.y&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, left_on=&apos;x&apos;, right_on=&apos;y&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;USING (k)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, on=&apos;k&apos;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LEFT JOIN ... WHERE b.col IS NULL&lt;/code&gt; (anti)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df_a[~df_a[&apos;k&apos;].isin(df_b[&apos;k&apos;])]&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JOIN ... ON range&lt;/code&gt; (PG, 비등호)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge_asof&lt;/code&gt;, &lt;code&gt;IntervalIndex&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;pandas 와 SQL 모두 동일한 set-theory 위에서 동작, 위 시각화는 pandas 와 공유한다.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-다대다-폭증&quot;&gt;1. 다대다 폭증&lt;/h3&gt;
&lt;p&gt;users 와 orders 모두 같은 키가 중복돼 있으면 결과 행 수가 곱셈으로 증가.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- users.id 가 1, 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- orders.user_id 가 1, 1, 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- → 2 × 3 = 6 행 (의도 아닐 수도)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;GROUP BY&lt;/code&gt; 또는 서브쿼리로 한쪽 unique 화.&lt;/p&gt;
&lt;h3 id=&quot;2-null-키리는-매칭-안-됨&quot;&gt;2. NULL 키리는 매칭 안 됨&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;col&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;col&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- 양쪽 NULL 이어도 매칭 X&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;col&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DISTINCT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;col&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     -- PostgreSQL, NULL=NULL 매칭&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-on-과-where-의-차이-특히-outer-join&quot;&gt;3. ON 과 WHERE 의 차이 (특히 OUTER JOIN)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- LEFT JOIN 에서 ON 조건은 결합 단계, WHERE 는 결합 후&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;paid&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Charlie 도 살아 있음 (왼쪽 보존)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;paid&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Charlie 가 사라짐 (WHERE 가 NULL 행 제거, INNER JOIN 처럼 동작)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;OUTER JOIN&lt;/code&gt; 에서 우측 컬럼 조건은 &lt;code&gt;ON&lt;/code&gt; 에 두는 게 의도와 맞을 때가 많다.&lt;/p&gt;
&lt;h3 id=&quot;4-select--의-컬럼-중복&quot;&gt;4. SELECT * 의 컬럼 중복&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; users&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; orders&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;user_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- id 컬럼이 양쪽에서 나옴, 어떤 게 어떤 건지 모호&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;명시적으로 &lt;code&gt;users.id&lt;/code&gt;, &lt;code&gt;orders.id AS order_id&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[SQL GROUP BY]]&lt;/li&gt;
&lt;li&gt;[[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas merge]]&lt;/li&gt;
&lt;li&gt;[[Pandas join]]&lt;/li&gt;
&lt;li&gt;[[Pandas concat]]&lt;/li&gt;
&lt;li&gt;[[External Merge Sort]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>join</category><category>dml</category><category>query</category><category>database</category><author>koa (김신건)</author></item><item><title>MySQL</title><link>https://shinkeonkim.com/wiki/sql/mysql/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/mysql/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MySQL&lt;/strong&gt; 은 1995 년 MySQL AB (스웨덴) 가 만들어 2008 년 Sun → 2010 년 Oracle 로 인수된 오픈소스 RDBMS. GPL + 상용 듀얼 라이선스.&lt;/p&gt;
&lt;p&gt;웹 백엔드의 사실상 표준 (LAMP/LEMP 스택). 단순함, 빠른 읽기, 풍부한 호스팅 옵션이 강점.&lt;/p&gt;
&lt;p&gt;2010 년 Oracle 인수 직후 원 개발자 Monty Widenius 가 포크해 &lt;strong&gt;MariaDB&lt;/strong&gt; 시작. 본 wiki 는 MySQL 8.0 기준, MariaDB 는 차이점만 언급.&lt;/p&gt;
&lt;p&gt;표준 SQL 의 골격은 [[SQL]] 참고. 본 wiki 는 MySQL &lt;strong&gt;dialect-specific&lt;/strong&gt; 한 부분만 정리.&lt;/p&gt;
&lt;h2 id=&quot;핵심-특성&quot;&gt;핵심 특성&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;InnoDB 가 기본 스토리지 엔진&lt;/strong&gt; (5.5+): ACID, MVCC, 외래키 지원&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MyISAM&lt;/strong&gt;: 트랜잭션·외래키 없음, 가벼움. 거의 안 씀 (시스템 테이블 외)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;격리 수준 기본 REPEATABLE READ&lt;/strong&gt;: PG 와 다름. gap lock 으로 phantom 까지 방지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AUTO_INCREMENT&lt;/strong&gt;: PK 자동 증가&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단순한 복제&lt;/strong&gt;: 비동기 master-replica (statement / row / mixed)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;상대적으로 느슨한 표준 적합성&lt;/strong&gt;: dialect 가 매우 강함&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;mysql-만의--두드러진-문법&quot;&gt;MySQL 만의 / 두드러진 문법&lt;/h2&gt;
&lt;h3 id=&quot;auto_increment&quot;&gt;AUTO_INCREMENT&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; users&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  id   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; AUTO_INCREMENT &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; VARCHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  email &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;255&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UNIQUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) ENGINE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;InnoDB &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CHARSET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, email) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;a@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LAST_INSERT_ID();     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 방금 INSERT 된 ID&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 시작값 조정&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users AUTO_INCREMENT &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;AUTO_INCREMENT&lt;/code&gt; 는 &lt;strong&gt;INSERT 가 롤백돼도 소비&lt;/strong&gt;. 빈 번호가 생긴다.&lt;/p&gt;
&lt;p&gt;[[SQL DDL]] 의 자동 증가 PK 비교 참고.&lt;/p&gt;
&lt;h3 id=&quot;on-duplicate-key-update-upsert&quot;&gt;ON DUPLICATE KEY UPDATE (UPSERT)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (email, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, login_count)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;alice@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DUPLICATE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;KEY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8.0.20 이하&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  login_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; login_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8.0.20+ : alias 권장 (VALUES() 가 deprecated)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (email, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, login_count)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;alice@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; new_row&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DUPLICATE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;KEY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; new_row&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  login_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; login_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;code&gt;ON DUPLICATE KEY UPDATE&lt;/code&gt; 는 충돌 여부와 무관하게 &lt;strong&gt;AUTO_INCREMENT 카운터를 소비&lt;/strong&gt;. 이를 피하려면 &lt;code&gt;INSERT IGNORE&lt;/code&gt; + &lt;code&gt;UPDATE&lt;/code&gt; 분리.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;insert-ignore--replace&quot;&gt;INSERT IGNORE / REPLACE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT IGNORE INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (email, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;alice@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 충돌하면 조용히 무시 (다른 에러도 묵살, 위험)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REPLACE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (email, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;alice@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 충돌하면 DELETE + INSERT, FK CASCADE 와 트리거가 함께 실행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- → 외부 관계 끊김 가능, 권장 안 함&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;limit--offset&quot;&gt;LIMIT + OFFSET&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; OFFSET &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 같은 의미 (offset, count)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG/표준은 &lt;code&gt;LIMIT n OFFSET m&lt;/code&gt; 또는 &lt;code&gt;FETCH FIRST n ROWS ONLY&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;limit-가-있는-update--delete&quot;&gt;LIMIT 가 있는 UPDATE / DELETE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; archived &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;2024-01-01&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;큰 테이블을 청크로 갱신할 때 매우 유용. PG 는 직접 지원하지 않고 CTE 우회.&lt;/p&gt;
&lt;h3 id=&quot;group_concat&quot;&gt;GROUP_CONCAT&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id, GROUP_CONCAT(tag &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tag SEPARATOR &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;,&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tags&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_tags&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 의 &lt;code&gt;STRING_AGG(tag, &apos;,&apos;)&lt;/code&gt; 에 대응. 기본 길이 제한 1024 (&lt;code&gt;group_concat_max_len&lt;/code&gt; 으로 확장 가능).&lt;/p&gt;
&lt;h3 id=&quot;json&quot;&gt;JSON&lt;/h3&gt;
&lt;p&gt;PG 의 JSONB 만큼 강력하진 않지만 충분히 쓸 만하다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PK AUTO_INCREMENT, payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events (payload) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;{&quot;user&quot;: 42, &quot;tags&quot;: [&quot;a&quot;,&quot;b&quot;], &quot;meta&quot;: {&quot;ip&quot;: &quot;1.2.3.4&quot;}}&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 추출&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;$.user&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 42 (JSON 값)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;$.user&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &apos;42&apos; (unquote, 문자)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       JSON_EXTRACT(payload, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$.meta.ip&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       JSON_UNQUOTE(payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;$.meta.ip&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 포함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; JSON_CONTAINS(payload, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;42&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$.user&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 갱신&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; JSON_SET(payload, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$.user&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;99&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; JSON_REMOVE(payload, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;$.meta.ip&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 인덱싱 (generated column 필요)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ADD&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; COLUMN user_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    GENERATED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ALWAYS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;$.user&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) VIRTUAL,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ADD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; idx_user_id (user_id);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8.0+ : multi-valued index for JSON arrays&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ADD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; idx_tags ((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CAST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;$.tags&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ARRAY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자세한 PG 와의 비교는 [[SQL Data Types]] 의 JSON 섹션 참고.&lt;/p&gt;
&lt;h3 id=&quot;full-text-인덱스&quot;&gt;Full-text 인덱스&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; articles&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  title &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;255&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  body  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TEXT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FULLTEXT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ft_body (title, body) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PARSER ngram     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 한국어/중국어&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) ENGINE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;InnoDB;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;MATCH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(title, body) AGAINST(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;database&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; NATURAL &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LANGUAGE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MODE) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; score&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; articles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; MATCH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(title, body) AGAINST(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;database&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; NATURAL &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LANGUAGE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MODE);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Boolean Mode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; articles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; MATCH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(title, body) AGAINST(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;+database -mongodb&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BOOLEAN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MODE);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 는 &lt;code&gt;tsvector&lt;/code&gt; + GIN 으로.&lt;/p&gt;
&lt;h3 id=&quot;정규식&quot;&gt;정규식&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; REGEXP &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;^A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; RLIKE &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;^A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 동의어&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; REGEXP_REPLACE(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;[0-9]&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; REGEXP_LIKE(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;^A.*&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);              &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;대소문자 구분은 collation 에 따른다 (&lt;code&gt;utf8mb4_general_ci&lt;/code&gt; 는 무시, &lt;code&gt;utf8mb4_bin&lt;/code&gt; 은 구분).&lt;/p&gt;
&lt;h3 id=&quot;사용자-변수와-흉내낸-윈도&quot;&gt;사용자 변수와 흉내낸 윈도&lt;/h3&gt;
&lt;p&gt;8.0 이전엔 윈도 함수가 없어 사용자 변수로 흉내.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 5.7, ROW_NUMBER() 흉내&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  @rn :&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @rn &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rn,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  city,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  salary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users, (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @rn :&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) r&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8.0+, 표준 윈도 함수 권장&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ROW_NUMBER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rn, city, salary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;8.0+ 에선 &lt;code&gt;ROW_NUMBER&lt;/code&gt;, &lt;code&gt;RANK&lt;/code&gt;, &lt;code&gt;LAG&lt;/code&gt;, &lt;code&gt;LEAD&lt;/code&gt; 등 표준 윈도 함수 전부 사용 가능.&lt;/p&gt;
&lt;h3 id=&quot;cte&quot;&gt;CTE&lt;/h3&gt;
&lt;p&gt;8.0+ 부터 지원 (5.x 엔 없음).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; RECURSIVE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; org &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, manager_id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; depth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employees &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; manager_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  UNION ALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;manager_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;depth&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employees e &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; org o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;manager_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; org;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;lateral-join&quot;&gt;LATERAL JOIN&lt;/h3&gt;
&lt;p&gt;8.0.14+ 부터 지원.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;LATERAL (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; amount &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;innodb-스토리지-엔진&quot;&gt;InnoDB 스토리지 엔진&lt;/h2&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;특성&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;ACID, MVCC&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준 트랜잭션&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;클러스터드 인덱스&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PK 가 물리적 행 순서 (PG 는 heap)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;보조 인덱스가 PK 참조&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;보조 인덱스 lookup 은 2 단계&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FK 지원&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MyISAM 은 미지원&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;행 단위 잠금&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;gap lock 으로 phantom 방지&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;자동 데드락 감지&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;한쪽 트랜잭션 롤백&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
InnoDB 의 클러스터드 인덱스 때문에 PK 선택이 매우 중요.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;단조 증가 PK&lt;/strong&gt; (AUTO_INCREMENT, ULID): 페이지 끝에 append, 빠름.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;랜덤 PK&lt;/strong&gt; (UUIDv4): 페이지 곳곳 쪼개기, 인덱스 fragmentation, 느려짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;UUID 가 PK 라면 v7 / ULID 같은 시간 정렬 형을 권장. &lt;code&gt;BINARY(16)&lt;/code&gt; 으로 저장 + &lt;code&gt;UUID_TO_BIN(uuid, 1)&lt;/code&gt; (swap_flag=1) 로 시간 prefix 정렬.&lt;/p&gt;
&lt;h2 id=&quot;sql_mode&quot;&gt;sql_mode&lt;/h2&gt;
&lt;p&gt;MySQL 의 SQL 행동을 제어하는 세션/글로벌 변수.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; @@sql_mode;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_DATE,...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sql_mode &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;STRICT_ALL_TABLES,NO_ZERO_DATE,ONLY_FULL_GROUP_BY&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;모드&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;STRICT_TRANS_TABLES&lt;/code&gt; / &lt;code&gt;STRICT_ALL_TABLES&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;잘못된 값에 에러 (안 켜면 조용히 잘림/0)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ONLY_FULL_GROUP_BY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GROUP BY 표준 강제. [[SQL GROUP BY]] 참고.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NO_ZERO_DATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;’0000-00-00’ 금지&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;NO_ENGINE_SUBSTITUTION&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;없는 엔진 요청 시 에러&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ANSI&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준 SQL 모드 (큰 비교: `&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;TRADITIONAL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;엄격 모드 묶음&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;5.7+ 부터 strict + ONLY_FULL_GROUP_BY 가 기본. 5.6 이하 마이그레이션 시 데이터 정합성 이슈 다수 발견.&lt;/p&gt;
&lt;h2 id=&quot;문자셋-collation&quot;&gt;문자셋, collation&lt;/h2&gt;
&lt;p&gt;가장 흔한 함정 중 하나. &lt;strong&gt;항상 utf8mb4&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DATABASE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; mydb&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CHARACTER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; utf8mb4 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COLLATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; utf8mb4_0900_ai_ci;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (...) ENGINE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;InnoDB &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CHARSET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;utf8mb4;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
MySQL 의 &lt;code&gt;utf8&lt;/code&gt; 은 &lt;strong&gt;3 바이트 utf8&lt;/strong&gt;, 이모지 (4 바이트) 가 들어가면 에러. &lt;strong&gt;항상 &lt;code&gt;utf8mb4&lt;/code&gt;&lt;/strong&gt; 를 써야 한다. MySQL 의 가장 악명 높은 함정.&lt;/p&gt;
&lt;/blockquote&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;collation&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8.0 기본, 악센트/대소문자 무시&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;utf8mb4_unicode_ci&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;5.7 흔함&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;utf8mb4_bin&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;바이트 단위 비교, 가장 엄격&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;utf8mb4_general_ci&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;빠르지만 부정확 (역사적), 권장 안 함&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;explain&quot;&gt;EXPLAIN&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN FORMAT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=JSON&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ...;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN ANALYZE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ...;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8.0.18+ (실제 실행 포함)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;컬럼&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;액세스 방법 (&lt;code&gt;const&lt;/code&gt;, &lt;code&gt;eq_ref&lt;/code&gt;, &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;range&lt;/code&gt;, &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;ALL&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;사용된 인덱스&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;rows&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;추정 검사 행 수&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Extra&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;Using index&lt;/code&gt;, &lt;code&gt;Using filesort&lt;/code&gt;, &lt;code&gt;Using temporary&lt;/code&gt; 등&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;type=ALL&lt;/code&gt; 은 풀스캔, 큰 테이블에선 경고 신호.&lt;/p&gt;
&lt;h2 id=&quot;트랜잭션과-잠금&quot;&gt;트랜잭션과 잠금&lt;/h2&gt;
&lt;p&gt;기본 격리 &lt;code&gt;REPEATABLE READ&lt;/code&gt; + gap lock. PG 와 다른 점:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;InnoDB 의 REPEATABLE READ 는 표준의 SERIALIZABLE 에 가까움&lt;/strong&gt; (phantom 방지).&lt;/li&gt;
&lt;li&gt;gap lock 으로 인해 의도치 않은 deadlock 이 발생할 수 있음.&lt;/li&gt;
&lt;li&gt;운영 트래픽이 많으면 &lt;code&gt;READ COMMITTED&lt;/code&gt; 로 낮추는 곳도 많다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TRANSACTION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ISOLATION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LEVEL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; READ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; COMMITTED&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;START TRANSACTION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 비관 잠금&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SHARE;       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 공유 잠금&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자세한 트랜잭션 모델은 [[SQL DCL TCL]].&lt;/p&gt;
&lt;h2 id=&quot;복제-replication&quot;&gt;복제 (Replication)&lt;/h2&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방식&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Statement-based&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;실행한 SQL 을 replica 가 다시 실행 (부동소수, NOW() 등에 문제)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Row-based&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;변경된 행을 그대로 (안전, 8.0 기본)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Mixed&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자동 선택&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;GTID (Global Transaction ID) 기반 복제가 8.0 표준. failover 가 단순해진다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;SHOW &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;REPLICA&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; STATUS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 8.0.22+ (이전 SLAVE STATUS)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;mariadb-와의-차이&quot;&gt;MariaDB 와의 차이&lt;/h2&gt;
&lt;p&gt;MariaDB 는 2010 년 포크된 이후 점점 다른 길. 주요 차이:&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL 8.0&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MariaDB 10.x/11.x&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;엔진&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;InnoDB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;InnoDB, Aria, ColumnStore, …&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;JSON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;네이티브 JSON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;텍스트 alias (LONGTEXT + 함수)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;윈도 함수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8.0+&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10.2+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;CTE&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8.0+&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10.2+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Sequences&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;없음 (AUTO_INCREMENT)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10.3+ SEQUENCE 지원&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;RETURNING&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;없음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10.5+ 일부 지원&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Roles&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8.0+&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10.0+&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;라이선스 측면에선 MariaDB 가 BSL 등 점점 비표준 라이선스 도입. MySQL 도 Oracle 영향으로 신뢰 이슈가 있어, 양쪽 다 주의 깊게 봐야 한다.&lt;/p&gt;
&lt;h2 id=&quot;mysql-vs-postgresql-요약&quot;&gt;MySQL vs PostgreSQL 요약&lt;/h2&gt;
&lt;p&gt;자세한 비교는 [[PostgreSQL]] 참고.&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;PostgreSQL&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;운영 단순성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 단순&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;보통 (autovacuum, 튜닝)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;읽기 성능 (단순)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;빠름&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;빠름&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;표준 적합성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;보통&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 높음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;트랜잭션 DDL&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;부분&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;전체&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;복잡한 분석 쿼리&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;약함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함 (CTE, 윈도, GIST)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;JSON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JSON + generated col 트릭&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JSONB (GIN 인덱스)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;라이선스&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GPL (Oracle)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL License&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;pandas-와-mysql&quot;&gt;pandas 와 MySQL&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sqlalchemy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; create_engine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;engine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; create_engine(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mysql+pymysql://user:pwd@host:3306/db?charset=utf8mb4&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd.read_sql(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  SELECT id, JSON_EXTRACT(payload, &apos;$.user&apos;) AS user_id, ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  FROM events&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  WHERE ts &gt;= DATE_SUB(NOW(), INTERVAL 7 DAY)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, engine)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df.to_sql(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;events_backup&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, engine, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;if_exists&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;append&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;          index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;chunksize&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;multi&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[[Pandas read_sql]] 의 &lt;code&gt;chunksize&lt;/code&gt; + &lt;code&gt;method=&apos;multi&apos;&lt;/code&gt; 패턴이 MySQL 대량 적재에 효과적. PG 의 &lt;code&gt;COPY&lt;/code&gt; 같은 네이티브 bulk 가 없어서.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;charset 미지정 시 latin1 로 해석돼 이모지/한글 깨짐. &lt;code&gt;?charset=utf8mb4&lt;/code&gt; 필수.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-utf8-vs-utf8mb4&quot;&gt;1. utf8 vs utf8mb4&lt;/h3&gt;
&lt;p&gt;이미 위에서. &lt;strong&gt;항상 utf8mb4&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2-묵시적-형변환&quot;&gt;2. 묵시적 형변환&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;a&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 1 (조용히 &apos;a&apos; → 0)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1abc&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- TRUE (1 = 1)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 는 에러, MySQL 은 조용한 버그. &lt;code&gt;STRICT&lt;/code&gt; 모드 + 명시적 &lt;code&gt;CAST&lt;/code&gt; 권장.&lt;/p&gt;
&lt;h3 id=&quot;3-auto_increment-의-갭&quot;&gt;3. AUTO_INCREMENT 의 갭&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... (id &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 할당)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROLLBACK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 5 는 안 돌아옴&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... (id &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 할당)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ID 가 연속이라고 가정하는 코드는 깨진다.&lt;/p&gt;
&lt;h3 id=&quot;4-datetime-vs-timestamp&quot;&gt;4. DATETIME vs TIMESTAMP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DATETIME&lt;/code&gt;: timezone 없음, 그대로 저장 (1000-9999)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;: 세션 timezone 으로 해석 → UTC 저장 → 다시 변환 (1970-2038)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt; 의 32-bit Unix time 제한 때문에 2038 년 문제. 큰 시간 범위 필요하면 &lt;code&gt;DATETIME&lt;/code&gt; + 애플리케이션 timezone 관리.&lt;/p&gt;
&lt;h3 id=&quot;5-enum-의-정렬&quot;&gt;5. ENUM 의 정렬&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ENUM(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;low&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;high&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; priority;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 정의 순으로 정렬 (low &amp;#x3C; medium &amp;#x3C; high)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;문자열 알파벳 순이 아닌, 정의 순서가 정렬 키. 의도일 수도, 사고일 수도.&lt;/p&gt;
&lt;h3 id=&quot;6-null-의-unique&quot;&gt;6. NULL 의 UNIQUE&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- MySQL InnoDB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (email &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;255&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UNIQUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 모두 허용!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- UNIQUE 는 NULL 끼리 중복으로 안 봄 (표준)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 도 동일. 표준 정의. 의도와 다르면 &lt;code&gt;NOT NULL&lt;/code&gt; 추가.&lt;/p&gt;
&lt;h3 id=&quot;7-on-delete-의-묵시적-동작&quot;&gt;7. ON DELETE 의 묵시적 동작&lt;/h3&gt;
&lt;p&gt;InnoDB 의 FK 가 &lt;code&gt;ON DELETE&lt;/code&gt; 옵션 없이 만들어지면 기본은 &lt;code&gt;RESTRICT&lt;/code&gt; (참조 있으면 부모 삭제 거부). 명시적으로 적는 게 안전.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DDL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[SQL JOIN]]&lt;/li&gt;
&lt;li&gt;[[SQL GROUP BY]]&lt;/li&gt;
&lt;li&gt;[[SQL DCL TCL]]&lt;/li&gt;
&lt;li&gt;[[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;[[PostgreSQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>database</category><category>rdbms</category><category>sql</category><category>mysql</category><category>innodb</category><author>koa (김신건)</author></item><item><title>PostgreSQL</title><link>https://shinkeonkim.com/wiki/sql/postgresql/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/postgresql/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; 은 1986 년 UC Berkeley 의 POSTGRES 프로젝트에서 출발해 1996 년 SQL 지원 버전으로 오픈소스화된 객체-관계형 DBMS (ORDBMS). PostgreSQL Global Development Group 이 관리, PostgreSQL License (BSD/MIT 계열).&lt;/p&gt;
&lt;p&gt;표준 SQL 적합성, &lt;strong&gt;확장성&lt;/strong&gt; (extension), 강력한 &lt;strong&gt;JSONB&lt;/strong&gt;, 풍부한 &lt;strong&gt;인덱스 종류&lt;/strong&gt;, 표준 호환 &lt;strong&gt;MVCC&lt;/strong&gt; 가 특징. “오픈소스의 Oracle”.&lt;/p&gt;
&lt;p&gt;표준 SQL 의 골격은 [[SQL]] 참고. 본 wiki 는 PostgreSQL &lt;strong&gt;dialect-specific&lt;/strong&gt; 한 부분만 정리.&lt;/p&gt;
&lt;h2 id=&quot;핵심-특성&quot;&gt;핵심 특성&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;표준 적합성 높음&lt;/strong&gt;: SQL:2023 의 상당 부분 구현.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MVCC&lt;/strong&gt;: 읽기-쓰기 비차단. 자세한 격리 수준은 [[SQL DCL TCL]] 참고.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;확장성&lt;/strong&gt;: &lt;code&gt;CREATE EXTENSION&lt;/code&gt; 으로 PostGIS, pg_trgm, hstore, vector (pgvector) 등.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSONB&lt;/strong&gt;: 바이너리 JSON, 인덱싱 + containment 강력.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;배열 / 범위 / 사용자 정의 타입&lt;/strong&gt;: 표준을 넘어선 풍부함.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;다양한 인덱스&lt;/strong&gt;: B-tree, Hash, GIN, GiST, BRIN, SP-GiST.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;트랜잭션 DDL&lt;/strong&gt;: &lt;code&gt;CREATE TABLE&lt;/code&gt; 도 롤백 가능. 마이그레이션 안정성에 결정적.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;postgresql-만의--두드러진-문법&quot;&gt;PostgreSQL 만의 / 두드러진 문법&lt;/h2&gt;
&lt;h3 id=&quot;serial-과-identity&quot;&gt;SERIAL 과 IDENTITY&lt;/h3&gt;
&lt;p&gt;[[SQL DDL]] 의 자동 증가 PK 비교 참고. 짧게:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 구식 (여전히 흔함)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SERIAL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 표준 (10+ 권장)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; GENERATED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ALWAYS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IDENTITY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; GENERATED&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IDENTITY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;SERIAL&lt;/code&gt; 은 실제로 시퀀스 + DEFAULT 의 sugar. 권한 관리, 백업/복원 시 약점이 있어 &lt;code&gt;IDENTITY&lt;/code&gt; 가 더 깔끔.&lt;/p&gt;
&lt;h3 id=&quot;returning&quot;&gt;RETURNING&lt;/h3&gt;
&lt;p&gt;INSERT/UPDATE/DELETE 의 결과를 즉시 반환. MySQL 에는 없는 강력한 기능.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;CodeWithOutput
language=“sql”
outputLanguage=“text”
code={`INSERT INTO users (name, city)
VALUES (‘Alice’, ‘Seoul’)
RETURNING id, created_at;&lt;/p&gt;
&lt;p&gt;UPDATE accounts
SET balance = balance - 100
WHERE id = 1 AND balance &gt;= 100
RETURNING balance;&lt;/p&gt;
&lt;p&gt;DELETE FROM events
WHERE created_at &amp;#x3C; NOW() - INTERVAL ‘30 day’
RETURNING id;&lt;code&gt;}   output={&lt;/code&gt; id |       created_at
----+------------------------
4 | 2026-06-20 14:23:01+09&lt;/p&gt;
&lt;h2 id=&quot;balance&quot;&gt;balance&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 900&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;— 삭제된 행들의 id 가 반환됨`}
/&gt;&lt;/p&gt;
&lt;p&gt;CTE 와 결합하면 한 쿼리로 복잡한 워크플로 처리.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; moved &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  DELETE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; staging &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; processed_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IS NOT NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  RETURNING &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; archive &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; moved;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;on-conflict-upsert&quot;&gt;ON CONFLICT (UPSERT)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (email, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, login_count)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;alice@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CONFLICT (email) DO &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; EXCLUDED&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    login_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; users&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;login_count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;RETURNING id, login_count;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 무시&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users (email, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;alice@x.com&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CONFLICT DO NOTHING;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 조건부 update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CONFLICT (email) DO &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; users&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;login_count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;race-condition 측면에서 가장 안전한 upsert. 동일 키에 충돌 시 atomic.&lt;/p&gt;
&lt;h3 id=&quot;jsonb&quot;&gt;JSONB&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SERIAL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PK, payload JSONB);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 인덱스&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_events_payload&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; GIN (payload);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_events_user&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events ((payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;user&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 연산자&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;         -- jsonb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        -- text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;{a,b,c}&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     -- 깊은 경로 (jsonb)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;{a,b,c}&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- 깊은 경로 (text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload @&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;{&quot;x&quot;:1}&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;     -- containment, GIN 인덱스 가능&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload ? &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;          -- key 존재&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload ?| &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;array&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&apos;a&apos;,&apos;b&apos;]  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 어느 key 라도 존재&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other_jsonb   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 병합&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 갱신 (15+)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jsonb_set(payload, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;{user}&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;99&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::jsonb);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;자세한 비교는 [[SQL Data Types]] 의 JSON 섹션 참고.&lt;/p&gt;
&lt;h3 id=&quot;배열&quot;&gt;배열&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; posts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SERIAL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PK, tags &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TEXT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tags @&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ARRAY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&apos;db&apos;];      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 포함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;sql&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ANY(tags);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts, unnest(tags) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 펼침&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array_agg(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 집계&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;정규식&quot;&gt;정규식&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ~ &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;^A&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 대소문자 구분&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ~&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;^a&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;         &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 대소문자 무시&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; REGEXP_REPLACE(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;[^a-zA-Z]&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; REGEXP_MATCHES(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;foo123bar456&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;[0-9]+&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;g&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- → {&apos;123&apos;}, {&apos;456&apos;} 두 행&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PostgreSQL 의 정규식은 POSIX 확장 + 일부 Perl 호환.&lt;/p&gt;
&lt;h3 id=&quot;윈도-함수와-partition-by&quot;&gt;윈도 함수와 PARTITION BY&lt;/h3&gt;
&lt;p&gt;표준이지만 PG 가 가장 풍부한 옵션을 가진다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  city,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  salary,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  RANK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()         &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rnk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  PERCENT_RANK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pct,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  AVG&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(salary)    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PARTITION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                       ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hired_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                       ROWS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BETWEEN&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRECEDING&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AND&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CURRENT &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ma&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WINDOW&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PARTITION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; salary &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;WINDOW&lt;/code&gt; 절로 윈도 정의를 이름 붙여 재사용. [[SQL GROUP BY]] 의 윈도 섹션 참고.&lt;/p&gt;
&lt;h3 id=&quot;cte-와-재귀&quot;&gt;CTE 와 재귀&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; RECURSIVE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; org &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id, manager_id, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; depth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employees &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; manager_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  UNION ALL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;manager_id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;depth&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; employees e &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; org o &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;manager_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; o&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; org &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; depth, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PG 12+ 부터 CTE 가 기본 inline. 이전엔 항상 materialize 라 옵티마이저 fence 로 활용했다 (현재는 &lt;code&gt;MATERIALIZED&lt;/code&gt; / &lt;code&gt;NOT MATERIALIZED&lt;/code&gt; 명시).&lt;/p&gt;
&lt;h3 id=&quot;lateral-join&quot;&gt;LATERAL JOIN&lt;/h3&gt;
&lt;p&gt;오른쪽 서브쿼리가 왼쪽의 컬럼을 참조 가능. “각 행마다 별도 쿼리”.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;recent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;amount&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;recent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;created_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users u&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;LEFT JOIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LATERAL (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; amount, created_at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; u&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) recent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TRUE;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;각 사용자의 최근 3 주문. MySQL 도 8.0.14+ 지원하지만 PG 가 먼저.&lt;/p&gt;
&lt;h3 id=&quot;distinct-on&quot;&gt;DISTINCT ON&lt;/h3&gt;
&lt;p&gt;표준이 아니지만 매우 유용. “그룹별 첫 행” 을 짧게.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT DISTINCT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (user_id) user_id, created_at, amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id, created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 각 user 의 가장 최근 주문 한 건&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;같은 결과를 윈도 함수로:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id, created_at, amount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ROW_NUMBER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;OVER&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PARTITION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; user_id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) rn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; orders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rn &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;mvcc-와-vacuum&quot;&gt;MVCC 와 VACUUM&lt;/h2&gt;
&lt;p&gt;PG 의 MVCC 는 UPDATE/DELETE 시 &lt;strong&gt;이전 버전을 삭제하지 않고 dead tuple 로 남긴다&lt;/strong&gt;. 트랜잭션이 끝나도 다른 트랜잭션이 볼 수 있어서 즉시 제거 불가.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;도구&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;역할&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VACUUM&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;dead tuple 회수 (공간 재사용)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VACUUM FULL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;테이블 재작성 (락 잡음, 운영 X)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ANALYZE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;통계 갱신 (옵티마이저 입력)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;autovacuum&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;백그라운드 자동 실행&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;dead tuple 누적 → 테이블 bloat → 쿼리 느려짐. autovacuum 튜닝이 운영 핵심 과제.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; relname, n_dead_tup, n_live_tup,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;       round&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(n_dead_tup::&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NULLIF&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(n_live_tup, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dead_pct&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pg_stat_user_tables&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n_dead_tup &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; LIMIT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;인덱스-종류&quot;&gt;인덱스 종류&lt;/h2&gt;
&lt;p&gt;표준에 없는 다양한 인덱스. [[SQL DDL]] 의 인덱스 섹션 참고.&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;종류&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;용도&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;B-tree&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;등호, 범위, ORDER BY (기본)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Hash&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;등호만 (B-tree 와 차이 미미)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;GIN&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JSONB, 배열, tsvector (풀텍스트)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;GiST&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;공간, 범위, 트라이그램&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;BRIN&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;거대 테이블 + 물리적 클러스터링 (시계열)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SP-GiST&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;비균형 트리 (전화번호 prefix 등)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- JSONB 부분 인덱스&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_active_users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; GIN ((payload &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;tags&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; active &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TRUE;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- BRIN, 수억 행 시계열에 효과적&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; idx_events_ts_brin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; BRIN (ts);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;explain&quot;&gt;EXPLAIN&lt;/h2&gt;
&lt;p&gt;쿼리 plan 확인.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;Seoul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN ANALYZE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ...;        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 실제 실행 (주의: UPDATE/DELETE 도 실행됨)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN (ANALYZE, BUFFERS, FORMAT &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ...;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;EXPLAIN ANALYZE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ...;     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 변경 후&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ROLLBACK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;                        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 되돌림 (PG 의 트랜잭션 DDL/DML 덕분)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;확장-extensions&quot;&gt;확장 (Extensions)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;CREATE EXTENSION&lt;/code&gt; 으로 기능 추가.&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;확장&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;용도&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pg_trgm&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;트라이그램, LIKE ‘%xx%’ 인덱스&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;postgis&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;공간 데이터&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pgvector&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;벡터 검색 (임베딩)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;hstore&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;key-value (JSONB 등장 전 흔히 썼음)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pg_stat_statements&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;쿼리 통계&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pgcrypto&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;해시, AES&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;uuid-ossp&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;UUID 생성기&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pg_partman&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;파티션 자동화&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;citus&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;분산 PG&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;파티셔닝&quot;&gt;파티셔닝&lt;/h2&gt;
&lt;p&gt;PG 10+ 부터 선언적 파티셔닝.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;BIGSERIAL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TIMESTAMPTZ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  payload JSONB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;PARTITION&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; BY&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; RANGE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (ts);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; events_2026q1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PARTITION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; OF events&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; VALUES&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2026-01-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2026-04-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; events_2026q2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PARTITION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; OF events&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  FOR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; VALUES&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2026-04-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;2026-07-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;조건: 파티션 키가 쿼리에 자주 등장해야 partition pruning 이 작동.&lt;/p&gt;
&lt;h2 id=&quot;복제--ha&quot;&gt;복제 / HA&lt;/h2&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방식&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Streaming Replication&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;WAL 을 replica 에 실시간 전송&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Logical Replication&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;publication/subscription 단위, 다른 버전 간 가능&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Patroni / repmgr&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자동 failover&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Foreign Data Wrapper&lt;/strong&gt; (FDW)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;다른 DB 를 외부 테이블로&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;postgresql-vs-mysql-요약&quot;&gt;PostgreSQL vs MySQL 요약&lt;/h2&gt;
&lt;p&gt;자세한 비교는 [[MySQL]] 참고.&lt;/p&gt;























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;PostgreSQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;표준 적합성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;보통 (개선 중)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;기본 격리 수준&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;READ COMMITTED&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;REPEATABLE READ (InnoDB)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;JSON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JSONB (인덱싱)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JSON (generated column 트릭)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;배열 타입&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✗&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FULL OUTER JOIN&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✗ (UNION 우회)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;RETURNING&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✗ (MariaDB 만)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;트랜잭션 DDL&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8.0 부분&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;라이선스&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PostgreSQL License (BSD 계열)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GPL (오라클 소유)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;풀텍스트&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;tsvector + GIN&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FULLTEXT 인덱스&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;pandas-와-postgresql&quot;&gt;pandas 와 PostgreSQL&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sqlalchemy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; create_engine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;engine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; create_engine(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;postgresql+psycopg2://user:pwd@host:5432/db&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd.read_sql(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  SELECT id, payload -&gt;&gt; &apos;user&apos; AS user_id, ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  FROM events&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  WHERE ts &gt;= NOW() - INTERVAL &apos;7 day&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, engine)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;대량 적재는 &lt;code&gt;COPY&lt;/code&gt; 가 가장 빠르다. [[Pandas read_sql]] 의 &lt;code&gt;psql_insert_copy&lt;/code&gt; 예제 참고.&lt;/p&gt;
&lt;p&gt;JSONB 컬럼을 pandas 로 읽으면 &lt;code&gt;dict&lt;/code&gt; (object dtype). 자주 쓰는 키는 SQL 단계에서 평탄화 후 가져오는 게 더 효율적.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-serial-의-시퀀스-권한&quot;&gt;1. SERIAL 의 시퀀스 권한&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INSERT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 그래도 INSERT 실패: 시퀀스 USAGE 권한 필요&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GRANT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; USAGE &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SEQUENCE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t_id_seq &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; alice;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;IDENTITY&lt;/code&gt; 는 이 문제가 없다.&lt;/p&gt;
&lt;h3 id=&quot;2-대소문자-식별자&quot;&gt;2. 대소문자 식별자&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MyTable&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&quot; (...);     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 따옴표 → 대소문자 보존&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MyTable;            &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 실패 (mytable 로 변환)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;MyTable&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- 성공&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;따옴표는 피하고 snake_case 권장.&lt;/p&gt;
&lt;h3 id=&quot;3-null-의-group-by&quot;&gt;3. NULL 의 GROUP BY&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- PG 는 NULL 그룹을 모음 (MySQL 도 동일)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; users &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;GROUP BY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; city;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-시간대-timestamptz&quot;&gt;4. 시간대 (TIMESTAMPTZ)&lt;/h3&gt;
&lt;p&gt;[[SQL Data Types]] 의 날짜·시간 섹션 참고. 운영은 항상 &lt;code&gt;TIMESTAMPTZ&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;5-autovacuum-끄기&quot;&gt;5. autovacuum 끄기&lt;/h3&gt;
&lt;p&gt;성능 이슈가 있어도 절대 끄지 말 것. 튜닝으로 해결 (&lt;code&gt;autovacuum_vacuum_scale_factor&lt;/code&gt;, &lt;code&gt;_threshold&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&quot;6-cte-의-최적화-변화&quot;&gt;6. CTE 의 최적화 변화&lt;/h3&gt;
&lt;p&gt;PG 11 이하: CTE 는 항상 머티리얼라이즈 (옵티마이저 fence).
PG 12+: 기본 inline. 강제하려면 &lt;code&gt;WITH ... AS MATERIALIZED ...&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SQL]]&lt;/li&gt;
&lt;li&gt;[[SQL DDL]]&lt;/li&gt;
&lt;li&gt;[[SQL DML]]&lt;/li&gt;
&lt;li&gt;[[SQL JOIN]]&lt;/li&gt;
&lt;li&gt;[[SQL GROUP BY]]&lt;/li&gt;
&lt;li&gt;[[SQL DCL TCL]]&lt;/li&gt;
&lt;li&gt;[[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;[[MySQL]]&lt;/li&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>database</category><category>rdbms</category><category>sql</category><category>postgresql</category><category>mvcc</category><author>koa (김신건)</author></item><item><title>SQL</title><link>https://shinkeonkim.com/wiki/sql/sql/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/sql/</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;SQL&lt;/strong&gt; (Structured Query Language) 은 관계형 데이터베이스 (RDBMS) 와 대화하기 위한 선언형 (declarative) 질의 언어. 1970 년 E.F. Codd 의 관계 모델 논문에서 출발, 1986 년 ANSI 표준화 (SQL-86), 이후 SQL:2023 까지 개정.&lt;/p&gt;
&lt;p&gt;“무엇을 (what)” 만 적고 “어떻게 (how)” 는 옵티마이저가 결정한다. 같은 결과를 만드는 실행 경로는 수천 가지일 수 있고, RDBMS 가 통계 기반으로 가장 빠른 길을 고른다.&lt;/p&gt;
&lt;h2 id=&quot;4-개의-하위-언어&quot;&gt;4 개의 하위 언어&lt;/h2&gt;
&lt;p&gt;표준 SQL 은 목적에 따라 4 개 카테고리로 나뉜다.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;카테고리&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;풀네임&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;키워드&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;용도&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;DDL&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Data Definition Language&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CREATE&lt;/code&gt;, &lt;code&gt;ALTER&lt;/code&gt;, &lt;code&gt;DROP&lt;/code&gt;, &lt;code&gt;TRUNCATE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;스키마 정의&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;DML&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Data Manipulation Language&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT&lt;/code&gt;, &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;데이터 조작&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;DCL&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Data Control Language&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GRANT&lt;/code&gt;, &lt;code&gt;REVOKE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;권한 제어&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;TCL&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Transaction Control Language&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BEGIN&lt;/code&gt;, &lt;code&gt;COMMIT&lt;/code&gt;, &lt;code&gt;ROLLBACK&lt;/code&gt;, &lt;code&gt;SAVEPOINT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;트랜잭션 제어&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;각 항목은 별도 wiki 로 깊이 다룬다, [[SQL DDL]] / [[SQL DML]] / [[SQL DCL TCL]].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;일부 문헌은 &lt;code&gt;SELECT&lt;/code&gt; 를 DQL (Data Query Language) 로 분리하기도 한다. ISO 표준은 DML 에 포함시킨다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;빠르게-보기&quot;&gt;빠르게 보기&lt;/h2&gt;
&lt;!-- mdx-component: CodeWithOutput --&gt;
&lt;h2 id=&quot;쿼리-실행의-논리적-순서&quot;&gt;쿼리 실행의 논리적 순서&lt;/h2&gt;
&lt;p&gt;작성 순서와 실행 순서는 다르다. &lt;code&gt;SELECT&lt;/code&gt; 를 먼저 쓰지만, 옵티마이저는 &lt;code&gt;FROM&lt;/code&gt; 부터 평가한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;center&quot;&gt;순서&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;절&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FROM&lt;/code&gt; / &lt;code&gt;JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;소스 테이블 결합&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;2&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;WHERE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;행 필터 (그룹화 전)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;3&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GROUP BY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;그룹 분할&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;HAVING&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;그룹 필터&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;5&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;컬럼 선택, 표현식 평가&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;6&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DISTINCT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중복 제거&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;7&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ORDER BY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정렬&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;8&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIMIT&lt;/code&gt; / &lt;code&gt;OFFSET&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;페이징&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;code&gt;WHERE&lt;/code&gt; 는 집계 결과를 참조할 수 없다 (&lt;code&gt;SELECT&lt;/code&gt; 보다 먼저 실행되니까). 집계 조건은 &lt;code&gt;HAVING&lt;/code&gt; 에 쓴다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;pandas-와의-11-대응&quot;&gt;pandas 와의 1:1 대응&lt;/h2&gt;
&lt;p&gt;[[Pandas]] 의 DataFrame 연산은 SQL 과 거의 대칭이다. 같은 개념의 두 표현.&lt;/p&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;SQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;pandas&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;비고&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SELECT col1, col2 FROM t&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[[&apos;col1&apos;, &apos;col2&apos;]]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;컬럼 선택&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;WHERE col &gt; 10&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[df[&apos;col&apos;] &gt; 10]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;[[Pandas Boolean Indexing]]&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ORDER BY col DESC&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.sort_values(&apos;col&apos;, ascending=False)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정렬&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIMIT 10&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.head(10)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;상위 N&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DISTINCT col&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df[&apos;col&apos;].unique()&lt;/code&gt; / &lt;code&gt;drop_duplicates&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중복 제거&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GROUP BY&lt;/code&gt; + &lt;code&gt;AVG(x)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.groupby(...).mean()&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;[[Pandas groupby]]&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;inner&apos;)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;[[Pandas merge]]&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.merge(a, b, how=&apos;left&apos;)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;[[Pandas merge]]&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;UNION ALL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;pd.concat([a, b])&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;[[Pandas concat]]&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;CASE WHEN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;np.where&lt;/code&gt; / &lt;code&gt;pd.cut&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;조건 분기&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;윈도 &lt;code&gt;ROW_NUMBER()&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.groupby(...).cumcount()&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;그룹 내 순번&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INSERT INTO&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;df.to_sql(...)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;[[Pandas read_sql]]&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;DB 와 직접 주고받는 통로는 [[Pandas read_sql]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;표준-sql-vs-dialect&quot;&gt;표준 SQL vs dialect&lt;/h2&gt;
&lt;p&gt;ANSI/ISO 표준은 골격, 실제 구현은 dialect 마다 차이가 크다.&lt;/p&gt;





















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;영역&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;표준 (SQL:2023)&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;PostgreSQL&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MySQL&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;자동 증가 PK&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;IDENTITY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;SERIAL&lt;/code&gt;, &lt;code&gt;GENERATED ... AS IDENTITY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;AUTO_INCREMENT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;문자열 결합&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;`&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;`&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;상위 N&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;FETCH FIRST n ROWS ONLY&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIMIT n&lt;/code&gt; (+ &lt;code&gt;FETCH&lt;/code&gt;)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIMIT n&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Upsert&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;MERGE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INSERT ... ON CONFLICT&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INSERT ... ON DUPLICATE KEY UPDATE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;부울&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOLEAN&lt;/code&gt; (네이티브)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOLEAN&lt;/code&gt; ≡ &lt;code&gt;TINYINT(1)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;JSON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt;, &lt;code&gt;JSONB&lt;/code&gt; (인덱싱 가능)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt; (인덱싱은 generated column)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;정규식&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIKE_REGEX&lt;/code&gt; (거의 미구현)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;~&lt;/code&gt;, &lt;code&gt;~*&lt;/code&gt;, &lt;code&gt;regexp_*&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;REGEXP&lt;/code&gt;, &lt;code&gt;RLIKE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;상세는 [[PostgreSQL]], [[MySQL]] 참고.&lt;/p&gt;
&lt;h2 id=&quot;데이터-타입-그룹&quot;&gt;데이터 타입 그룹&lt;/h2&gt;
&lt;p&gt;연산은 타입에 따라 가능 여부와 결과가 달라진다.&lt;/p&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;그룹&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;예&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;주요 연산&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;숫자&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTEGER&lt;/code&gt;, &lt;code&gt;BIGINT&lt;/code&gt;, &lt;code&gt;NUMERIC&lt;/code&gt;, &lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;산술, 집계, &lt;code&gt;ROUND/CEIL/FLOOR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;문자열&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;VARCHAR&lt;/code&gt;, &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;CHAR&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;LIKE&lt;/code&gt;, 정규식, &lt;code&gt;CONCAT&lt;/code&gt;, &lt;code&gt;SUBSTRING&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;날짜/시간&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;DATE&lt;/code&gt;, &lt;code&gt;TIMESTAMP&lt;/code&gt;, &lt;code&gt;TIMESTAMPTZ&lt;/code&gt;, &lt;code&gt;INTERVAL&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;차이, 추출, 트런케이션, &lt;code&gt;INTERVAL&lt;/code&gt; 산술&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;부울&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, &lt;code&gt;NOT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;이진&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;BYTEA&lt;/code&gt; (PG), &lt;code&gt;BLOB&lt;/code&gt; (MySQL)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;길이, 해시, 인코딩&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;JSON&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;JSON&lt;/code&gt;, &lt;code&gt;JSONB&lt;/code&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;경로 추출, containment, 인덱스&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;배열&lt;/strong&gt; (PG)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;INTEGER[]&lt;/code&gt;, &lt;code&gt;TEXT[]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;ANY/ALL&lt;/code&gt;, 슬라이싱, &lt;code&gt;unnest&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;공간&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;GEOMETRY&lt;/code&gt;, &lt;code&gt;GEOGRAPHY&lt;/code&gt; (PostGIS)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;거리, 포함, 교차&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;타입별 연산은 [[SQL Data Types]] 에서 자세히.&lt;/p&gt;
&lt;h2 id=&quot;null-의-3-값-논리&quot;&gt;NULL 의 3-값 논리&lt;/h2&gt;
&lt;p&gt;SQL 의 가장 까다로운 부분.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;        &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL (FALSE 가 아님)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; IS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL 포함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; COUNT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(col) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- NULL 제외&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;비교 결과가 &lt;code&gt;TRUE&lt;/code&gt; / &lt;code&gt;FALSE&lt;/code&gt; / &lt;code&gt;NULL&lt;/code&gt; 3 가지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WHERE&lt;/code&gt; 절은 &lt;code&gt;TRUE&lt;/code&gt; 인 행만 통과 (&lt;code&gt;NULL&lt;/code&gt; 도 제외)&lt;/li&gt;
&lt;li&gt;집계 함수는 &lt;code&gt;NULL&lt;/code&gt; 을 자동 무시 (단 &lt;code&gt;COUNT(*)&lt;/code&gt; 는 행 자체를 셈)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NULL&lt;/code&gt; 비교는 &lt;code&gt;IS NULL&lt;/code&gt; / &lt;code&gt;IS NOT NULL&lt;/code&gt; / &lt;code&gt;IS DISTINCT FROM&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;학습-경로&quot;&gt;학습 경로&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;스키마&lt;/strong&gt;: [[SQL DDL]]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 조작&lt;/strong&gt;: [[SQL DML]]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결합&lt;/strong&gt;: [[SQL JOIN]]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;집계&lt;/strong&gt;: [[SQL GROUP BY]]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;권한·트랜잭션&lt;/strong&gt;: [[SQL DCL TCL]]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;타입별 연산&lt;/strong&gt;: [[SQL Data Types]]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;dialect&lt;/strong&gt;: [[PostgreSQL]], [[MySQL]]&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[Pandas read_sql]]&lt;/li&gt;
&lt;li&gt;[[Pandas merge]]&lt;/li&gt;
&lt;li&gt;[[Pandas groupby]]&lt;/li&gt;
&lt;li&gt;[[Redis]] (대비, NoSQL key-value)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>sql</category><category>database</category><category>rdbms</category><category>query-language</category><author>koa (김신건)</author></item><item><title>Redis</title><link>https://shinkeonkim.com/wiki/sql/redis/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/sql/redis/</guid><pubDate>Mon, 15 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Redis&lt;/strong&gt; (REmote DIctionary Server)는 인메모리 키-값 저장소이다. Salvatore Sanfilippo가 2009년 만들었고, 현재는 Redis Ltd. 가 개발을 주도한다. BSD 라이선스 (7.4부터는 RSALv2/SSPLv1 듀얼).&lt;/p&gt;
&lt;p&gt;메모리에 데이터를 올려 microsecond 단위 응답 속도를 제공한다. 캐시, 세션 저장소, 메시지 브로커, 리더보드 등에 쓰인다.&lt;/p&gt;
&lt;h2 id=&quot;핵심-특성&quot;&gt;핵심 특성&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Single-threaded event loop&lt;/strong&gt;: 명령 처리는 단일 스레드, I/O multiplexing (epoll/kqueue)으로 동시 처리&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;영속성 옵션&lt;/strong&gt;: RDB snapshot 또는 AOF (append-only file) 로 디스크 백업 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;복제(Replication)&lt;/strong&gt;: master-replica 구조, 비동기 복제&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pub/Sub&lt;/strong&gt;: [[pubsub-bus]] 메시지 브로커 기능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;트랜잭션&lt;/strong&gt;: MULTI/EXEC로 명령 묶기, ACID는 아님 (격리 수준 낮음)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;데이터-타입&quot;&gt;데이터 타입&lt;/h2&gt;























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;타입&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;설명&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;주요 사용처&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;String&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;바이너리 안전 문자열, 최대 512MB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;캐시, counter (INCR/DECR)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;List&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;연결 리스트, 양끝 삽입/삭제 O(1)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;큐, 최근 항목 목록&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Hash&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;field-value 맵&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;객체 저장 (user:1 → {name, email})&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Set&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중복 없는 문자열 집합&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;태그, 멤버십, 집합 연산&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Sorted Set&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;스코어로 정렬된 집합&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;리더보드, 타임라인&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Stream&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;append-only 로그, consumer group&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;이벤트 소싱, 메시지 큐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;HyperLogLog&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;확률적 카디널리티 추정&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;unique visitor 카운팅 (메모리 절약)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Geo&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;경도/위도 좌표, 반경 검색&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;위치 기반 서비스&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Bitmap&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;비트 배열 (String 기반)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;출석 체크, feature flag&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;영속성-persistence&quot;&gt;영속성 (Persistence)&lt;/h2&gt;























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방식&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;동작&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;장점&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;단점&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;RDB&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;주기적 snapshot (SAVE/BGSAVE)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;파일 작음, 복구 빠름&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;마지막 snapshot 이후 데이터 손실 가능&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;AOF&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모든 쓰기 명령 로그&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;손실 최소화 (fsync 정책 따라)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;파일 큼, 복구 느림 (REWRITE 필요)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;혼용 가능 (RDB + AOF). fsync 정책: &lt;code&gt;always&lt;/code&gt; (느리지만 안전) / &lt;code&gt;everysec&lt;/code&gt; (기본, 최대 1초 손실) / &lt;code&gt;no&lt;/code&gt; (OS 관리).&lt;/p&gt;
&lt;h2 id=&quot;복제고가용성&quot;&gt;복제·고가용성&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Master-Replica&lt;/strong&gt;: 비동기 복제, replica는 읽기 전용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sentinel&lt;/strong&gt;: 자동 failover, 모니터링, 알림&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster&lt;/strong&gt;: 수평 확장, 16384 슬롯 hash partitioning, 노드 장애 시 자동 failover&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cluster는 단일 명령이 여러 슬롯에 걸치면 실행 불가 (hash tag &lt;code&gt;{user:1}&lt;/code&gt; 로 회피 가능).&lt;/p&gt;
&lt;h2 id=&quot;캐싱-패턴&quot;&gt;캐싱 패턴&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;패턴&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;설명&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;장단점&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Cache-aside&lt;/strong&gt; (Look-aside)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;앱이 읽기 전 캐시 확인 → miss면 DB 읽고 캐시 갱신&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가장 흔함, 캐시/DB 불일치 가능&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Write-through&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;쓰기마다 캐시+DB 동시 갱신&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;일관성 높음, 쓰기 느림&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Write-behind&lt;/strong&gt; (Write-back)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;캐시 먼저 쓰고 비동기로 DB 반영&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;쓰기 빠름, 장애 시 손실 위험&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;TTL (Time-To-Live) + Eviction policy (메모리 부족 시):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;noeviction&lt;/code&gt;: 쓰기 거부&lt;/li&gt;
&lt;li&gt;&lt;code&gt;allkeys-lru&lt;/code&gt;, &lt;code&gt;allkeys-lfu&lt;/code&gt;: 전체 키 중 LRU/LFU 제거&lt;/li&gt;
&lt;li&gt;&lt;code&gt;volatile-lru&lt;/code&gt;, &lt;code&gt;volatile-lfu&lt;/code&gt;: TTL 있는 키만 대상&lt;/li&gt;
&lt;li&gt;&lt;code&gt;allkeys-random&lt;/code&gt;, &lt;code&gt;volatile-random&lt;/code&gt;: 무작위 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;주요-사용처&quot;&gt;주요 사용처&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;캐시&lt;/strong&gt;: DB 쿼리 결과, API 응답, 세션 데이터&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session Store&lt;/strong&gt;: 분산 환경에서 사용자 세션 공유&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate Limiting&lt;/strong&gt;: INCR + EXPIRE로 요청 수 제한&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Leaderboard&lt;/strong&gt;: Sorted Set으로 랭킹 실시간 갱신&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pub/Sub Bus&lt;/strong&gt;: 실시간 알림, 채팅 메시지 브로커&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queue&lt;/strong&gt;: List (LPUSH/RPOP) 또는 Stream + consumer group&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;분산 락&lt;/strong&gt;: SETNX + EXPIRE (Redlock 알고리즘)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;약점주의점&quot;&gt;약점·주의점&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;메모리 비용&lt;/strong&gt;: 모든 데이터가 RAM에, 큰 데이터셋은 비쌈&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single-thread 제약&lt;/strong&gt;: 무거운 연산 (KEYS *, SMEMBERS 큰 Set) 은 전체 차단&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key 단위 Atomicity&lt;/strong&gt;: 여러 키 걸친 트랜잭션은 롤백 불가 (MULTI/EXEC는 isolation 약함)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 일관성&lt;/strong&gt;: 비동기 복제라 failover 시 일부 쓰기 손실 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;네트워크 비용&lt;/strong&gt;: 클라이언트-서버 왕복, 파이프라이닝으로 완화&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>database</category><category>in-memory</category><category>key-value</category><category>nosql</category><category>cache</category><author>koa (김신건)</author></item></channel></rss>