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),...

ОсвСн описанитС ΠΏΠΎ-Π³ΠΎΡ€Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ с "ΠΏΡ€Π΅Π·Π°Π»Π΅ΠΏΠ²Π°Π½Π΅Ρ‚ΠΎ" Π½Π° заявката, Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° Π½ΠΈ Π΄ΠΎΠ²Π΅Π΄Π΅ ΠΈ Π΄ΠΎ Π½Π΅Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½Π° ΠΏΠ°ΠΌΠ΅Ρ‚ ΠΈ срив Π½Π° ΡΡŠΡ€Π²ΡŠΡ€Π°. ΠŸΡ€ΠΈΡ‡ΠΈΠ½Π°Ρ‚Π° Π΅ проста - PG Π·Π°ΠΏΠ°Π·Π²Π° Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½Π° ΠΏΠ°ΠΌΠ΅Ρ‚ Π·Π° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅, Π° броят Π½Π° записитС Π² Π½Π°Π±ΠΎΡ€Π° Π΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ само ΠΎΡ‚ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Wishlist Π½Π° бизнСс Π»ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π°. Π’ особСно ΠΊΠ»ΠΈΠ½ΠΈΡ‡Π½ΠΈ случаи Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС Π²ΠΈΠ΄ΠΈ "Π½ΠΎΠΌΠ΅Ρ€ΠΈΡ€Π°Π½ΠΈ" Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈ, ΠΏΠΎ-Π³ΠΎΠ»Π΅ΠΌΠΈ ΠΎΡ‚ $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 |

JSON

Π—Π°ΠΏΠΎΡ‡Π²Π°ΠΉΠΊΠΈ с вСрсия 9.3, PostgreSQL въвСдС ΠΏΡŠΠ»Π½ΠΎΡ†Π΅Π½Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с Ρ‚ΠΈΠΏΠ° json. Π•Ρ‚ΠΎ Π·Π°Ρ‰ΠΎ, Π°ΠΊΠΎ Π²Π°ΡˆΠΈΡ‚Π΅ Π²Ρ…ΠΎΠ΄Π½ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ са Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½ΠΈ Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π°, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ Ρ‚Π°ΠΌ ΠΈ Π΄Π° Ρ„ΠΎΡ€ΠΌΠΈΡ€Π°Ρ‚Π΅ json ΠΎΠ±Π΅ΠΊΡ‚ Π·Π° SQL заявка:

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И Π² pg_type, pg_depend, pg_attribute, pg_attrdef, ... β€” ΠΈ ΠΈΠ·ΠΎΠ±Ρ‰ΠΎ Π½ΠΈΡ‰ΠΎ.

Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ, Π² ΡƒΠ΅Π± систСми с голям Π±Ρ€ΠΎΠΉ ΠΊΡ€Π°Ρ‚ΠΊΠΎΡ‚Ρ€Π°ΠΉΠ½ΠΈ Π²Ρ€ΡŠΠ·ΠΊΠΈ Π·Π° всяка ΠΎΡ‚ тях, Ρ‚Π°ΠΊΠ°Π²Π° Ρ‚Π°Π±Π»ΠΈΡ†Π° Ρ‰Π΅ Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° всСки ΠΏΡŠΡ‚ Π½ΠΎΠ²ΠΈ систСмни записи, ΠΊΠΎΠΈΡ‚ΠΎ сС ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ ΠΏΡ€ΠΈ затварянС Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π° към Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ. Π’ ΠΊΡ€Π°ΠΉΠ½Π° смСтка, Π½Π΅ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€Π°Π½ΠΎΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° TEMP TABLE Π²ΠΎΠ΄ΠΈ Π΄ΠΎ "ΠΏΠΎΠ΄ΡƒΠ²Π°Π½Π΅" Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†ΠΈΡ‚Π΅ Π² pg_catalog ΠΈ забавянС Π½Π° ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Π³ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚.
Π Π°Π·Π±ΠΈΡ€Π° сС, с Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π±ΠΎΡ€ΠΈ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ΠΈΡ‡Π΅Π½ пропуск VACUUM FULL спорСд систСмнитС ΠΊΠ°Ρ‚Π°Π»ΠΎΠΆΠ½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ.

ΠŸΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° сСсията

Π”Π° ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Π΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°Ρ‚Π° Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΎΡ‚ ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈΡ случай Π΅ доста слоТна Π·Π° Π΅Π΄Π½Π° SQL заявка, Π½ΠΎ искатС Π΄Π° я ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ доста чСсто. ВоСст искамС Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π² DO Π±Π»ΠΎΠΊ, Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° прСнос Π½Π° Π΄Π°Π½Π½ΠΈ Ρ‡Ρ€Π΅Π· Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ Ρ‰Π΅ бъдС Ρ‚Π²ΡŠΡ€Π΄Π΅ скъпо.

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ $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

Има Π΄Ρ€ΡƒΠ³ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ, Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π½Π° Π΄Ρ€ΡƒΠ³ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Π½ΠΈ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π½ΠΈ Π΅Π·ΠΈΡ†ΠΈ.

Π—Π½Π°Π΅Ρ‚Π΅ Π»ΠΈ ΠΎΡ‰Π΅ Π½Π°Ρ‡ΠΈΠ½ΠΈ? Π‘ΠΏΠΎΠ΄Π΅Π»Π΅Ρ‚Π΅ Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅!

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€