๋๋๋ก ๊ฐ๋ฐ์์๊ฒ ํ์ํ ๋งค๊ฐ๋ณ์ ์งํฉ ๋๋ ์ ์ฒด ์ ํ์ ์์ฒญ์ ์ ๋ฌ "์
๊ตฌ์์". ๋๋๋ก ์ด ๋ฌธ์ ์ ๋ํ ๋งค์ฐ ์ด์ํ ํด๊ฒฐ์ฑ
์ด ์์ต๋๋ค.
"๋ฐ๋์์" ๊ฐ์ ์ด๋ป๊ฒ ํ๋ฉด ์๋๋์ง, ์, ์ด๋ป๊ฒ ํ๋ฉด ๋ ์ํ ์ ์๋์ง ์์๋ด
์๋ค.
์์ฒญ ๋ณธ๋ฌธ์ ๊ฐ์ ์ง์ "์ฝ์ "
์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ ๋๋ค.
query = "SELECT * FROM tbl WHERE id = " + value
... ๋๋ ์ด์ ๊ฐ์ด:
query = "SELECT * FROM tbl WHERE id = :param".format(param=value)
์ด ๋ฐฉ๋ฒ์ ๋ํด ๋งํ๊ณ , ์ฐ๊ณ ,
๊ฑฐ์ ํญ์ ๊ทธ๋ ์ต๋๋ค SQL ์ฝ์
์ ๋ํ ์ง์ ๊ฒฝ๋ก ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ๊ฐ์ ๋ก "์ ์ฐฉ"ํด์ผ ํ๋ ๋น์ฆ๋์ค ๋ก์ง์ ๋ํ ์ถ๊ฐ ๋ถํ.
์ด ์ ๊ทผ ๋ฐฉ์์ ํ์ํ ๊ฒฝ์ฐ์๋ง ๋ถ๋ถ์ ์ผ๋ก ์ ๋นํ๋ ์ ์์ต๋๋ค. ํํฐ์ ๋ ์ฌ์ฉ ๋ณด๋ค ํจ์จ์ ์ธ ๊ณํ์ ์ํด PostgreSQL ๋ฒ์ 10 ์ดํ์์. ์ด ๋ฒ์ ์์ ์ค์บ ์น์ ๋ชฉ๋ก์ ์ ์ก๋ ๋งค๊ฐ๋ณ์๋ฅผ ๊ณ ๋ คํ์ง ์๊ณ ์์ฒญ ๋ณธ๋ฌธ์ ๊ธฐ์ค์ผ๋ก๋ง ๊ฒฐ์ ๋ฉ๋๋ค.
$n ์ธ์
์ฌ์ฉ
์ธ์์ ๊ฐ๋ณ ๊ฐ์
์ ์ ์๋ ์์ ์ธ์๋ฅผ ๋ฏธ๋ฆฌ ์ ๋ฌํ๋ ค๊ณ ํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒ์ ๋๋ค.
... id IN ($1, $2, $3, ...) -- $1 : 2, $2 : 3, $3 : 5, ...
์ด ์์์ ์์ฒญ์ ๋จ๊ธฐ๋ฉด ์ ์ฌ์ ์ธ ์ฃผ์ ์ผ๋ก๋ถํฐ ์ฐ๋ฆฌ๋ฅผ ๊ตฌํ ์ ์์ง๋ง ์ฌ์ ํ ์์ฒญ์ ๋ถ์ด๊ฑฐ๋ ํ์ฑํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค. ์ธ์ ์์์ ๊ฐ ์ต์ ์ ๋ํด. ๋งค๋ฒํ๋ ๊ฒ๋ณด๋ค ์ด๋ฏธ ๋ซ์ง ๋ง ๊ทธ๊ฒ ์์ด๋ ํ ์ ์์ต๋๋ค.
๋ค์์ ํฌํจํ๋ ํ๋์ ๋งค๊ฐ๋ณ์๋ง ์ ๋ฌํ๋ฉด ์ถฉ๋ถํฉ๋๋ค. ๋ฐฐ์ด์ ์ง๋ ฌํ๋ ํํ:
... id = ANY($1::integer[]) -- $1 : '{2,3,5,8,13}'
์ ์ผํ ์ฐจ์ด์ ์ ์ธ์๋ฅผ ์ํ๋ ๋ฐฐ์ด ์ ํ์ผ๋ก ๋ช ์์ ์ผ๋ก ๋ณํํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ์ด๋๋ก ๊ฐ๊ณ ์๋์ง ๋ฏธ๋ฆฌ ์๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๋ฅผ ์ผ์ผํค์ง ์์ต๋๋ค.
์ํ ์ ์ก(๋งคํธ๋ฆญ์ค)
์ผ๋ฐ์ ์ผ๋ก ์ด๋ค์ "ํ ๋ฒ์ ์์ฒญ์ผ๋ก" ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฝ์ ํ๊ธฐ ์ํด ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ ์กํ๊ธฐ ์ํ ๋ชจ๋ ์ข ๋ฅ์ ์ต์ ์ ๋๋ค.
INSERT INTO tbl(k, v) VALUES($1,$2),($3,$4),...
์์์ ์ค๋ช ํ ์์ฒญ์ "์ฌ์ ์ฐฉ" ๋ฌธ์ ์ธ์๋ ์ด๋ก ์ธํด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ ๊ทธ๋ฆฌ๊ณ ์๋ฒ ์ถฉ๋. ์ด์ ๋ ๊ฐ๋จํฉ๋๋ค. PG๋ ์ธ์์ ๋ํ ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์์ฝํ๊ณ ์ธํธ์ ๋ ์ฝ๋ ์๋ ๋น์ฆ๋์ค ๋ก์ง ์ ํ๋ฆฌ์ผ์ด์ ์์๋ฆฌ์คํธ์ ์ํด์๋ง ์ ํ๋ฉ๋๋ค. ํนํ ์์ ์ฌ๋ก์์ ๋ณผ ํ์๊ฐ ์์์ต๋๋ค. $9000๋ณด๋ค ํฐ "๋ฒํธ๊ฐ ๋งค๊ฒจ์ง" ์ธ์ - ์ด๋ ๊ฒ ํ์ง ๋ง์ธ์.
์ด๋ฏธ ์ ์ฉํ์ฌ ์ฟผ๋ฆฌ๋ฅผ ๋ค์ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค. "XNUMX๋จ๊ณ" ์ง๋ ฌํ:
INSERT INTO tbl
SELECT
unnest[1]::text k
, unnest[2]::integer v
FROM (
SELECT
unnest($1::text[])::text[] -- $1 : '{"{a,1}","{b,2}","{c,3}","{d,4}"}'
) T;
์, ๋ฐฐ์ด ๋ด๋ถ์ "๋ณต์กํ" ๊ฐ์ ๊ฒฝ์ฐ ๋ฐ์ดํ๋ก ๋ฌถ์ด์ผ ํฉ๋๋ค.
์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์์์ ์์ ํ๋๋ก ์ ํ ํญ๋ชฉ์ "ํ์ฅ"ํ ์ ์์์ด ๋ถ๋ช
ํฉ๋๋ค.
์ธ๋ค์คํธ, ์ธ๋ค์คํธ, โฆ
๋๋๋ก ๋ด๊ฐ ์ธ๊ธํ "๋ฐฐ์ด์ ๋ฐฐ์ด" ๋์ ์ฌ๋ฌ "์ด์ ๋ฐฐ์ด"์ ์ ๋ฌํ๋ ์ต์
์ด ์์ต๋๋ค.
SELECT
unnest($1::text[]) k
, unnest($2::integer[]) v;
์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ์๋ก ๋ค๋ฅธ ์ด์ ๋ํ ๊ฐ ๋ชฉ๋ก์ ์์ฑํ ๋ ์ค์๋ฅผ ํ๋๋ผ๋ ์์ ํ ์์์น ๋ชปํ ๊ฒฐ๊ณผ, ๋ํ ์๋ฒ ๋ฒ์ ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค.
-- $1 : '{a,b,c}', $2 : '{1,2}'
-- PostgreSQL 9.4
k | v
-----
a | 1
b | 2
c | 1
a | 2
b | 1
c | 2
-- PostgreSQL 11
k | v
-----
a | 1
b | 2
c |
JSON
๋ฒ์ 9.3๋ถํฐ PostgreSQL์๋ json ์ ํ ์์ ์ ์ํ ์์ ํ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ ์ ๋ ฅ ๋งค๊ฐ๋ณ์๊ฐ ๋ธ๋ผ์ฐ์ ์ ์ ์๋์ด ์์ผ๋ฉด ๋ฐ๋ก ๊ฑฐ๊ธฐ์์ ์์์ ์์ฑํ ์ ์์ต๋๋ค. SQL ์ฟผ๋ฆฌ์ฉ json ๊ฐ์ฒด:
SELECT
key k
, value v
FROM
json_each($1::json); -- '{"a":1,"b":2,"c":3,"d":4}'
์ด์ ๋ฒ์ ์ ๊ฒฝ์ฐ์๋ ๋์ผํ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ฐ๊ฐ(hstore), ๊ทธ๋ฌ๋ hstore์์ ๋ณต์กํ ๊ฐ์ฒด๋ฅผ ์ด์ค์ผ์ดํ ์ฒ๋ฆฌํ์ฌ ์ฌ๋ฐ๋ฅธ "์ ๊ธฐ"๋ฅผ ์ํํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
json_populate_recordset
"์ ๋ ฅ" json ๋ฐฐ์ด์ ๋ฐ์ดํฐ๊ฐ ์ผ๋ถ ํ ์ด๋ธ์ ์ฑ์ธ ๊ฒ์ด๋ผ๋ ๊ฒ์ ๋ฏธ๋ฆฌ ์๊ณ ์๋ ๊ฒฝ์ฐ "์ญ์ฐธ์กฐ" ํ๋์ json_populate_recordset ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ ์ ํ์ผ๋ก ์บ์คํ ํ๋ ๋ฐ ๋ง์ ๋น์ฉ์ ์ ์ฝํ ์ ์์ต๋๋ค.
SELECT
*
FROM
json_populate_recordset(
NULL::pg_class
, $1::json -- $1 : '[{"relname":"pg_class","oid":1262},{"relname":"pg_namespace","oid":2615}]'
);
json_to_recordset
๊ทธ๋ฆฌ๊ณ ์ด ํจ์๋ ํ ์ด๋ธ ํ์์ ์์กดํ์ง ์๊ณ ๋จ์ํ ์ ๋ฌ๋ ๊ฐ์ฒด ๋ฐฐ์ด์ ์ ํ ํญ๋ชฉ์ผ๋ก "ํ์ฅ"ํฉ๋๋ค.
SELECT
*
FROM
json_to_recordset($1::json) T(k text, v integer);
-- $1 : '[{"k":"a","v":1},{"k":"b","v":2}]'
k | v
-----
a | 1
b | 2
์์ ํ ์ด๋ธ
๊ทธ๋ฌ๋ ์ ์ก๋ ์ํ์ ๋ฐ์ดํฐ ์์ด ๋งค์ฐ ํฐ ๊ฒฝ์ฐ ์ด๋ฅผ ํ๋์ ์ง๋ ฌํ๋ ๋งค๊ฐ๋ณ์์ ๋์ง๋ ๊ฒ์ ์ด๋ ต๊ณ ๋๋ก๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๋์ฉ๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น. ์๋ฅผ ๋ค์ด ์ธ๋ถ ์์คํ ์์ ์ค๋ ์๊ฐ ๋์ ๋๊ท๋ชจ ์ด๋ฒคํธ ๋ฐ์ดํฐ ๋ฐฐ์น๋ฅผ ์์งํ ๋ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธก์์ ์ผํ์ฑ์ผ๋ก ์ฒ๋ฆฌํ๋ ค๊ณ ํฉ๋๋ค.
์ด ๊ฒฝ์ฐ ๊ฐ์ฅ ์ข์ ์๋ฃจ์
์ ๋ค์์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
CREATE TEMPORARY TABLE tbl(k text, v integer);
...
INSERT INTO tbl(k, v) VALUES($1, $2); -- ะฟะพะฒัะพัะธัั ะผะฝะพะณะพ-ะผะฝะพะณะพ ัะฐะท
...
-- ััั ะดะตะปะฐะตะผ ััะพ-ัะพ ะฟะพะปะตะทะฝะพะต ัะพ ะฒัะตะน ััะพะน ัะฐะฑะปะธัะตะน ัะตะปะธะบะพะผ
๋ฐฉ๋ฒ์ด ์ข๋ค ๋์ฉ๋์ ๊ฐํ์ ์ธ ์ ์ก์ ์ํด ๋ฐ์ดํฐ.
๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ค๋ช
ํ๋ ๊ด์ ์์ ๋ณผ ๋ ์์ ํ
์ด๋ธ์ "์ผ๋ฐ" ํ
์ด๋ธ๊ณผ ํ ๊ฐ์ง ๊ธฐ๋ฅ๋ง ๋ค๋ฆ
๋๋ค. pg_class ์์คํ
ํ
์ด๋ธ์์, ๋ฐ c pg_type, pg_depend, pg_attribute, pg_attrdef, ... โ ๊ทธ๋ฆฌ๊ณ ์ ํ.
๋ฐ๋ผ์ ๊ฐ๊ฐ์ ๋ํด ๋จ๊ธฐ ์ฐ๊ฒฐ์ด ๋ง์ ์น ์์คํ
์์ ์ด๋ฌํ ํ
์ด๋ธ์ ๋งค๋ฒ ์๋ก์ด ์์คํ
๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ด ๋ซํ ๋ ์ญ์ ๋ฉ๋๋ค. ๊ฒฐ๊ตญ, TEMP TABLE์ ํต์ ํ์ง ์๊ณ ์ฌ์ฉํ๋ฉด pg_catalog์ ํ
์ด๋ธ์ด "ํฝ์ฐฝ"ํฉ๋๋ค. ์ด๋ฅผ ์ฌ์ฉํ๋ ๋ง์ ์์
์๋๊ฐ ๋๋ ค์ง๋๋ค.
๋ฌผ๋ก ์ด๊ฒ์ ๋ค์๊ณผ ๊ฐ์ด ์ธ์ธ ์ ์์ต๋๋ค. ์ฃผ๊ธฐ์ ํจ์ค VACUUM FULL ์์คํ
์นดํ๋ก๊ทธ ํ
์ด๋ธ์ ๋ฐ๋ผ.
์ธ์ ๋ณ์
์ด์ ์ฌ๋ก์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ๋จ์ผ SQL ์ฟผ๋ฆฌ์ ๋ํด ์๋นํ ๋ณต์กํ์ง๋ง ์์ฃผ ์ํํ๋ ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ์ฆ, ์ ์ฐจ์ ์ฒ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ต๋๋ค.
๋ํ $n ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ต๋ช ๋ธ๋ก์ผ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ์ธ์ ๋ณ์์ ํจ์๋ ์ฐ๋ฆฌ๊ฐ ์ํฉ์์ ๋ฒ์ด๋๋๋ก ๋์์ค ๊ฒ์ ๋๋ค. ํ์ฌ ์ค์ .
๋ฒ์ 9.2 ์ด์ ์๋ ๋ฏธ๋ฆฌ ๊ตฌ์ฑํด์ผ ํ์ต๋๋ค.
SET my.val = '{1,2,3}';
DO $$
DECLARE
id integer;
BEGIN
FOR id IN (SELECT unnest(current_setting('my.val')::integer[])) LOOP
RAISE NOTICE 'id : %', id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
-- NOTICE: id : 1
-- NOTICE: id : 2
-- NOTICE: id : 3
์ง์๋๋ ๋ค๋ฅธ ์ ์ฐจ์ ์ธ์ด๋ก ์ฌ์ฉํ ์ ์๋ ๋ค๋ฅธ ์๋ฃจ์ ์ด ์์ต๋๋ค.
๋ ๋ง์ ๋ฐฉ๋ฒ์ ์๊ณ ๊ณ์ญ๋๊น? ์๊ฒฌ์ ๊ณต์ ํ์ญ์์ค!
์ถ์ฒ : habr.com