PostgreSQL Antipatterns: ืคืึธืจืŸ ืฉื˜ืขืœื˜ ืื•ืŸ ืกืึทืœืขืงืฅ ืฆื• SQL

ืคื•ืŸ ืฆื™ื™ื˜ ืฆื• ืฆื™ื™ื˜ ืึท ื“ืขื•ื•ืขืœืึธืคึผืขืจ ื“ืึทืจืฃ ืคืึธืจืŸ ืึท ืกื›ื•ื ืคื•ืŸ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืึธื“ืขืจ ืืคื™ืœื• ืึท ื’ืึทื ืฅ ืกืขืœืขืงืฆื™ืข ืฆื• ื“ื™ ื‘ืขื˜ืŸ "ื‘ื™ื™ึท ื“ื™ ืึทืจื™ื™ึทื ื’ืึทื ื’". ืžืืœ ืื™ืจ ืงื•ืžืขืŸ ืึทืจื™ื‘ืขืจ ื–ื™ื™ืขืจ ืžืึธื“ื ืข ืกืึทืœื•ืฉืึทื ื– ืฆื• ื“ืขื ืคึผืจืึธื‘ืœืขื.
PostgreSQL Antipatterns: ืคืึธืจืŸ ืฉื˜ืขืœื˜ ืื•ืŸ ืกืึทืœืขืงืฅ ืฆื• SQL
ืœืึธืžื™ืจ ื’ื™ื™ืŸ ืฆื•ืจื™ืง ืื•ืŸ ื–ืขืŸ ื•ื•ืึธืก ื ื™ื˜ ืฆื• ื˜ืึธืŸ, ื•ื•ืึธืก, ืื•ืŸ ื•ื•ื™ ืžื™ืจ ืงืขื ืขืŸ ื˜ืึธืŸ ื“ืึธืก ื‘ืขืกืขืจ.

ื“ื™ืจืขืงื˜ ื™ื ืกืขืจืฉืึทืŸ ืคื•ืŸ ื•ื•ืึทืœื•ืขืก ืื™ืŸ ื“ื™ ื‘ืขื˜ืŸ ื’ื•ืฃ

ืขืก ื™ื•ื–ืฉืึทื•ื•ืึทืœื™ ืงื•ืงื˜ ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก:

query = "SELECT * FROM tbl WHERE id = " + value

... ืึธื“ืขืจ ื•ื•ื™ ื“ืึธืก:

query = "SELECT * FROM tbl WHERE id = :param".format(param=value)

ื“ืขื ืื•ืคึฟืŸ ืื™ื– ื’ืขื–ืื’ื˜, ื’ืขืฉืจื™ื‘ืŸ ืื•ืŸ ืืคื™ืœื• ืฆื™ืขืŸ ืฉืขืคืข:

PostgreSQL Antipatterns: ืคืึธืจืŸ ืฉื˜ืขืœื˜ ืื•ืŸ ืกืึทืœืขืงืฅ ืฆื• SQL

ื›ึผืžืขื˜ ืฉื˜ืขื ื“ื™ืง ื“ืึธืก ืื™ื– ื“ื™ืจืขืงื˜ ื“ืจืš ืฆื• 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),...

ืื™ืŸ ืึทื“ื™ืฉืึทืŸ ืฆื• ื“ื™ ืคึผืจืึธื‘ืœืขืžืก ื“ื™ืกืงืจื™ื™ื‘ื“ ืื•ื™ื‘ืŸ ืžื™ื˜ "ืฉื™ื™ึทืขืš-ื’ืœื•ื™ื ื’" ื“ื™ ื‘ืงืฉื”, ื“ืึธืก ืงืขืŸ ืื•ื™ืš ืคื™ืจืŸ ืื•ื ื“ื– ืฆื• ืื•ื™ืก ืคื•ืŸ ื–ื›ึผืจื•ืŸ ืื•ืŸ ืกืขืจื•ื•ืขืจ ืงืจืึทืš. ื“ื™ ืกื™ื‘ื” ืื™ื– ืคึผืฉื•ื˜ - ืคึผื’ ืจื™ื–ืขืจื•ื•ื– ื ืึธืš ื–ื™ืงืึธืจืŸ ืคึฟืึทืจ ืึทืจื’ื•ืžืขื ื˜ืŸ, ืื•ืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจืขืงืึธืจื“ืก ืื™ืŸ ื“ืขื ื’ืึทื ื’ ืื™ื– ืœื™ืžื™ื˜ืขื“ ื‘ืœื•ื™ื– ื“ื•ืจืš ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ื‘ืื“ืขืจืคืขื ื™ืฉืŸ ืคื•ืŸ ื“ื™ ื’ืขืฉืขืคื˜ ืœืึธื’ื™ืง. ืื™ืŸ ื“ืขืจ ื”ื•ื™ืคึผื˜ ืงืœื™ื ื™ืฉ ืงืึทืกืขืก ืื™ืš ื’ืขื”ืื˜ ืฆื• ื–ืขืŸ "ื ื•ืžืขืจ" ืึทืจื’ื•ืžืขื ื˜ืŸ ื–ืขื ืขืŸ ืžืขืจ ื•ื•ื™ $ 9000 - ื˜ืึธืŸ ื ื™ื˜ ื˜ืึธืŸ ื“ืึธืก.

ื–ืืœ ืก ืจื™ืจื™ื™ื˜ ื“ื™ ื‘ืงืฉื” ื ื™ืฆืŸ ืฉื•ื™ืŸ "ืฆื•ื•ื™ื™-ืžื“ืจื’ื”" ืกื™ืจื™ืึทืœื™ื–ื™ื™ืฉืึทืŸ:

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 |

ื“ื–ืฉืกืึธืŸ

ื–ื™ื ื˜ ื•ื•ืขืจืกื™ืข 9.3, PostgreSQL ื”ืื˜ ืคื•ืœ-ืคืœืขื“ื–ืฉื“ ืคืึทื ื’ืงืฉืึทื ื– ืคึฟืึทืจ ืืจื‘ืขื˜ืŸ ืžื™ื˜ ื“ื™ json ื˜ื™ืคึผ. ื“ืขืจื™ื‘ืขืจ, ืื•ื™ื‘ ื“ื™ ื“ืขืคึฟื™ื ื™ืฆื™ืข ืคื•ืŸ โ€‹โ€‹ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืึทืงืขืจื– ืื™ืŸ ื“ื™ื™ืŸ ื‘ืœืขื˜ืขืจืขืจ, โ€‹โ€‹ืื™ืจ ืงืขื ืขืŸ ืคืึธืจืขื ืขืก ืจืขื›ื˜ ื“ืึธืจื˜ json ื›ื™ื™ืคืขืฅ ืคึฟืึทืจ SQL ืึธื ืคึฟืจืขื’:

SELECT
  key k
, value v
FROM
  json_each($1::json); -- '{"a":1,"b":2,"c":3,"d":4}'

ืคึฟืึทืจ ืคืจื™ื™ึทืขืจื“ื™ืง ื•ื•ืขืจืกื™ืขืก, ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืื•ืคึฟืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ื™ืขื“ืขืจ (ื”ืกื˜ืึธืจ), ืึธื‘ืขืจ ืจื™ื›ื˜ื™ืง "ืงืึธื ื•ื•ืึทืœื•ืฉืึทืŸ" ืžื™ื˜ ื™ืกืงื™ื™ืคึผื™ื ื’ ืงืึธืžืคึผืœืขืงืก ืึทื‘ื“ื–ืฉืขืงืฅ ืื™ืŸ ื”ืกื˜ืึธืจืข ืงืขื ืขืŸ ื’ืจื•ื ื˜ ืคึผืจืึธื‘ืœืขืžืก.

json_populate_recordset

ืื•ื™ื‘ ืื™ืจ ื•ื•ื™ืกืŸ ืื™ืŸ ืฉื˜ื™ื™ึทื’ืŸ ืึทื– ื“ื™ ื“ืึทื˜ืŸ ืคื•ืŸ ื“ื™ "ื™ื ืคึผื•ื˜" ื“ื–ืฉืกืึธืŸ ืžืขื ื’ืข ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ืฆื• ืคึผืœืึธืžื‘ื™ืจืŸ ืขื˜ืœืขื›ืข ื˜ื™ืฉ, ืื™ืจ ืงืขื ืขืŸ ืจืึทื˜ืขื•ื•ืขืŸ ืึท ืคึผืœืึทืฅ ืื™ืŸ "ื“ืขืจืขืคืขื ืกื™ื ื’" ืคืขืœื“ืขืจ ืื•ืŸ ืงืึทืกื˜ื™ื ื’ ื–ื™ื™ ืฆื• ื“ื™ ืคืืจืœืื ื’ื˜ ื˜ื™ื™ืคึผืก ื“ื•ืจืš ื ื™ืฆืŸ ื“ื™ 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 ืกื™ืกื˜ืขื ื˜ื™ืฉืื•ืŸ ืื™ืŸ pg_type, pg_depend, pg_attribute, pg_attrdef, ... - ื’ืืจื ื™ืฉื˜.

ื“ืขืจื™ื‘ืขืจ, ืื™ืŸ ื•ื•ืขื‘ ืกื™ืกื˜ืขืžืขืŸ ืžื™ื˜ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ืงื•ืจืฅ-ื’ืขืœืขื‘ื˜ ืงืึทื ืขืงืฉืึทื ื– ืคึฟืึทืจ ื™ืขื“ืขืจ ืคื•ืŸ ื–ื™ื™, ืึทื–ืึท ืึท ื˜ื™ืฉ ื•ื•ืขื˜ ื“ื–ืฉืขื ืขืจื™ื™ื˜ ื ื™ื™ึท ืกื™ืกื˜ืขื ืจืขืงืึธืจื“ืก ื™ืขื“ืขืจ ืžืึธืœ, ื•ื•ืึธืก ื–ืขื ืขืŸ ืื•ื™ืกื’ืขืžืขืงื˜ ื•ื•ืขืŸ ื“ื™ ืงืฉืจ ืฆื• ื“ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก ืื™ื– ืคืืจืžืื›ื˜. ืฆื•ื ืกื•ืฃ, ืึทื ืงืึทื ื˜ืจืึธื•ืœื“ ื ื•ืฆืŸ ืคื•ืŸ TEMP TABLE ืคื™ืจื˜ ืฆื• "ื’ืขืฉื•ื•ื™ืœืขื›ืฅ" ืคื•ืŸ ื˜ื™ืฉืŸ ืื™ืŸ pg_catalog ืื•ืŸ ืกืœืึธื•ื™ื ื’ ืึทืจืึธืคึผ ืคื™ืœืข ืึทืคึผืขืจื™ื™ืฉืึทื ื– ื•ื•ืึธืก ื ื•ืฆืŸ ื–ื™ื™.
ืคื•ืŸ ืงื•ืจืก, ื“ืขื ืงืขื ืขืŸ ื–ื™ื™ืŸ ื“ืขืœื˜ ืžื™ื˜ ื ื™ืฆืŸ ืคึผืขืจื™ืึธื“ื™ืฉ ื“ื•ืจื›ืคืึธืจ ื•ื•ืึทืงื•ื•ื ืคื•ืœ ืœื•ื™ื˜ ื“ื™ ืกื™ืกื˜ืขื ืงืึทื˜ืึทืœืึธื’ ื˜ื™ืฉืŸ.

ืกืขืกื™ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื–

ื–ืืœ ืก ื™ื‘ืขืจื ืขืžืขืŸ ืึทื– ืคึผืจืึทืกืขืกื™ื ื’ ื“ื™ ื“ืึทื˜ืŸ ืคื•ืŸ ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ืคืึทืœ ืื™ื– ื’ืึทื ืฅ ืงืึธืžืคึผืœื™ืฆื™ืจื˜ ืคึฟืึทืจ ืื™ื™ืŸ SQL ืึธื ืคึฟืจืขื’, ืึธื‘ืขืจ ืื™ืจ ื•ื•ื™ืœืŸ ืฆื• ื˜ืึธืŸ ื“ืึธืก ื’ืึทื ืฅ ืึธืคื˜. ืึทื– ืื™ื–, ืžื™ืจ ื•ื•ื™ืœืŸ ืฆื• ื ื•ืฆืŸ ืคึผืจืึทืกื™ื“ื–ืฉืขืจืึทืœ ืคึผืจืึทืกืขืกื™ื ื’ ืื™ืŸ DO block, ืึธื‘ืขืจ ื ื™ืฆืŸ ื“ืึทื˜ืŸ ืึทืจื™ื‘ืขืจืคื™ืจืŸ ื“ื•ืจืš ืฆื™ื™ึทื˜ื•ื•ื™ื™ึทืœื™ืง ื˜ื™ืฉืŸ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืฆื• ื˜ื™ื™ึทืขืจ.

ืžื™ืจ ืงืขื ืขืŸ ืื•ื™ืš ื ื™ืฉื˜ ื ื•ืฆืŸ $ n-ืคึผืึทืจืึทืžืขื˜ืขืจืก ืฆื• ืคืึธืจืŸ ืฆื• ืึทืŸ ืึทื ืึธื ื™ืžืข ื‘ืึทื ื•ืฆืขืจืก ื‘ืœืึธืง. ืกืขืกื™ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื– ืื•ืŸ ื“ื™ ืคึฟื•ื ืงืฆื™ืข ื•ื•ืขื˜ ื”ืขืœืคึฟืŸ ืื•ื ื“ื– ื‘ืึทืงื•ืžืขืŸ ืื•ื™ืก ืคื•ืŸ ื“ืขื ืกื™ื˜ื•ืึทืฆื™ืข ืงืจืึทื ื˜_ืกืขื˜ื˜ื™ื ื’.

ืื™ื™ื“ืขืจ ื•ื•ืขืจืกื™ืข 9.2 ืขืก ืื™ื– ื ื™ื™ื˜ื™ืง ืฆื• ืคืึทืจ-ืงืึทื ืคื™ื’ื™ืขืจ ืกืคึผืขืฆื™ืขืœืข ื ืึธืžืขืŸ ืคึผืœืึทืฅ custom_variable_classes ืคึฟืึทืจ "ื“ื™ื™ืŸ" ืกืขืกื™ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื–. ืื•ื™ืฃ ืงืจืึทื ื˜ ื•ื•ืขืจืกื™ืขืก ืื™ืจ ืงืขื ืขืŸ ืฉืจื™ื™ึทื‘ืŸ ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก:

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

ืื ื“ืขืจืข ืกืึทืœื•ืฉืึทื ื– ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขืคึฟื•ื ืขืŸ ืื™ืŸ ืื ื“ืขืจืข ื’ืขืฉื˜ื™ืฆื˜ ืคึผืจืึทืกื™ื“ื–ืฉืขืจืึทืœ ืฉืคึผืจืึทื›ืŸ.

ืฆื™ ืื™ืจ ื•ื•ื™ืกืŸ ืงื™ื™ืŸ ืื ื“ืขืจืข ื•ื•ืขื’ืŸ? ื™ื™ึทื ื˜ื™ื™ืœืŸ ืื™ืŸ ื“ื™ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ!

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’