ಕಾಲಕಾಲಕ್ಕೆ, ಡೆವಲಪರ್ ಅಗತ್ಯವಿದೆ ವಿನಂತಿಗೆ ನಿಯತಾಂಕಗಳ ಸೆಟ್ ಅಥವಾ ಸಂಪೂರ್ಣ ಆಯ್ಕೆಯನ್ನು ರವಾನಿಸಿ "ದ್ವಾರದಲ್ಲಿ". ಕೆಲವೊಮ್ಮೆ ಈ ಸಮಸ್ಯೆಗೆ ಬಹಳ ವಿಚಿತ್ರವಾದ ಪರಿಹಾರಗಳಿವೆ.
ನಾವು "ವಿರುದ್ಧದಿಂದ" ಹೋಗೋಣ ಮತ್ತು ಅದನ್ನು ಹೇಗೆ ಮಾಡಬಾರದು, ಏಕೆ ಮತ್ತು ನೀವು ಅದನ್ನು ಹೇಗೆ ಉತ್ತಮವಾಗಿ ಮಾಡಬಹುದು ಎಂಬುದನ್ನು ನೋಡೋಣ.
ವಿನಂತಿಯ ದೇಹದಲ್ಲಿ ಮೌಲ್ಯಗಳ ನೇರ "ಅಳವಡಿಕೆ"
ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಈ ರೀತಿ ಕಾಣುತ್ತದೆ:
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),...
ವಿನಂತಿಯ "ಮರು-ಅಂಟುವಿಕೆ" ಯೊಂದಿಗೆ ಮೇಲೆ ವಿವರಿಸಿದ ಸಮಸ್ಯೆಗಳ ಜೊತೆಗೆ, ಇದು ನಮಗೆ ಕಾರಣವಾಗಬಹುದು ನೆನಪಿಲ್ಲ ಮತ್ತು ಸರ್ವರ್ ಕ್ರ್ಯಾಶ್. ಕಾರಣ ಸರಳವಾಗಿದೆ - ಪಿಜಿ ಆರ್ಗ್ಯುಮೆಂಟ್ಗಳಿಗೆ ಹೆಚ್ಚುವರಿ ಮೆಮೊರಿಯನ್ನು ಕಾಯ್ದಿರಿಸುತ್ತದೆ ಮತ್ತು ಸೆಟ್ನಲ್ಲಿನ ದಾಖಲೆಗಳ ಸಂಖ್ಯೆಯು ವ್ಯಾಪಾರ ಲಾಜಿಕ್ ಅಪ್ಲಿಕೇಶನ್ ವಿಶ್ಲಿಸ್ಟ್ನಿಂದ ಮಾತ್ರ ಸೀಮಿತವಾಗಿರುತ್ತದೆ. ವಿಶೇಷವಾಗಿ ಕ್ಲಿನಿಕಲ್ ಪ್ರಕರಣಗಳಲ್ಲಿ ಅದನ್ನು ನೋಡುವುದು ಅಗತ್ಯವಾಗಿತ್ತು $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;
ಹೌದು, ರಚನೆಯೊಳಗಿನ "ಸಂಕೀರ್ಣ" ಮೌಲ್ಯಗಳ ಸಂದರ್ಭದಲ್ಲಿ, ಅವುಗಳನ್ನು ಉಲ್ಲೇಖಗಳೊಂದಿಗೆ ರಚಿಸಬೇಕಾಗಿದೆ.
ಈ ರೀತಿಯಾಗಿ ನೀವು ಅನಿಯಂತ್ರಿತ ಸಂಖ್ಯೆಯ ಕ್ಷೇತ್ರಗಳೊಂದಿಗೆ ಆಯ್ಕೆಯನ್ನು "ವಿಸ್ತರಿಸಬಹುದು" ಎಂಬುದು ಸ್ಪಷ್ಟವಾಗಿದೆ.
unnest, unnest,…
ಕಾಲಕಾಲಕ್ಕೆ ನಾನು ಪ್ರಸ್ತಾಪಿಸಿದ "ವ್ಯೂಹಗಳ ರಚನೆಯ" ಹಲವಾರು "ಕಾಲಮ್ಗಳ ಸರಣಿ" ಬದಲಿಗೆ ಹಾದುಹೋಗುವ ಆಯ್ಕೆಗಳಿವೆ.
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 ರಿಂದ ಪ್ರಾರಂಭಿಸಿ, ಪೋಸ್ಟ್ಗ್ರೆಎಸ್ಕ್ಯುಎಲ್ json ಪ್ರಕಾರದೊಂದಿಗೆ ಕೆಲಸ ಮಾಡಲು ಪೂರ್ಣ ಪ್ರಮಾಣದ ಕಾರ್ಯಗಳನ್ನು ಹೊಂದಿದೆ. ಆದ್ದರಿಂದ, ನಿಮ್ಮ ಇನ್ಪುಟ್ ನಿಯತಾಂಕಗಳನ್ನು ಬ್ರೌಸರ್ನಲ್ಲಿ ವ್ಯಾಖ್ಯಾನಿಸಿದರೆ, ನೀವು ಅಲ್ಲಿಯೇ ಮತ್ತು ಫಾರ್ಮ್ ಮಾಡಬಹುದು SQL ಪ್ರಶ್ನೆಗೆ json ಆಬ್ಜೆಕ್ಟ್:
SELECT
key k
, value v
FROM
json_each($1::json); -- '{"a":1,"b":2,"c":3,"d":4}'
ಹಿಂದಿನ ಆವೃತ್ತಿಗಳಿಗೆ, ಅದೇ ವಿಧಾನವನ್ನು ಬಳಸಬಹುದು ಪ್ರತಿ (ಅಂಗಡಿ), ಆದರೆ 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 ನಲ್ಲಿ ಕೋಷ್ಟಕಗಳ "ಊತ" ಕ್ಕೆ ಕಾರಣವಾಗುತ್ತದೆ ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸುವ ಅನೇಕ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿಧಾನಗೊಳಿಸುತ್ತದೆ.
ಸಹಜವಾಗಿ, ಇದರೊಂದಿಗೆ ಹೋರಾಡಬಹುದು ಆವರ್ತಕ ಪಾಸ್ ನಿರ್ವಾತ ಪೂರ್ಣ ಸಿಸ್ಟಮ್ ಕ್ಯಾಟಲಾಗ್ ಕೋಷ್ಟಕಗಳ ಪ್ರಕಾರ.
ಸೆಷನ್ ವೇರಿಯಬಲ್ಸ್
ಹಿಂದಿನ ಪ್ರಕರಣದ ಡೇಟಾದ ಪ್ರಕ್ರಿಯೆಯು ಒಂದೇ 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
ಇತರ ಬೆಂಬಲಿತ ಕಾರ್ಯವಿಧಾನದ ಭಾಷೆಗಳಲ್ಲಿ ಇತರ ಪರಿಹಾರಗಳು ಲಭ್ಯವಿವೆ.
ಹೆಚ್ಚಿನ ಮಾರ್ಗಗಳು ತಿಳಿದಿದೆಯೇ? ಕಾಮೆಂಟ್ಗಳಲ್ಲಿ ಹಂಚಿಕೊಳ್ಳಿ!
ಮೂಲ: www.habr.com