ಅನುಮಾನಾಸ್ಪದ ವಿಧಗಳು

ಅವರ ನೋಟದಲ್ಲಿ ಅನುಮಾನಾಸ್ಪದ ಏನೂ ಇಲ್ಲ. ಇದಲ್ಲದೆ, ಅವರು ನಿಮಗೆ ಚೆನ್ನಾಗಿ ಮತ್ತು ದೀರ್ಘಕಾಲದವರೆಗೆ ಪರಿಚಿತರಾಗಿದ್ದಾರೆ. ಆದರೆ ನೀವು ಅವುಗಳನ್ನು ಪರಿಶೀಲಿಸುವವರೆಗೆ ಮಾತ್ರ. ಇಲ್ಲಿ ಅವರು ತಮ್ಮ ಕಪಟ ಸ್ವಭಾವವನ್ನು ತೋರಿಸುತ್ತಾರೆ, ನೀವು ನಿರೀಕ್ಷಿಸಿದ್ದಕ್ಕಿಂತ ಸಂಪೂರ್ಣವಾಗಿ ವಿಭಿನ್ನವಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತಾರೆ. ಮತ್ತು ಕೆಲವೊಮ್ಮೆ ಅವರು ನಿಮ್ಮ ಕೂದಲನ್ನು ತುದಿಯಲ್ಲಿ ನಿಲ್ಲುವಂತೆ ಮಾಡುತ್ತಾರೆ - ಉದಾಹರಣೆಗೆ, ಅವರು ಅವರಿಗೆ ವಹಿಸಿಕೊಟ್ಟ ರಹಸ್ಯ ಡೇಟಾವನ್ನು ಕಳೆದುಕೊಳ್ಳುತ್ತಾರೆ. ನೀವು ಅವರನ್ನು ಎದುರಿಸಿದಾಗ, ಅವರು ಒಬ್ಬರಿಗೊಬ್ಬರು ತಿಳಿದಿಲ್ಲವೆಂದು ಅವರು ಹೇಳಿಕೊಳ್ಳುತ್ತಾರೆ, ಆದರೂ ನೆರಳಿನಲ್ಲಿ ಅವರು ಒಂದೇ ಹುಡ್ ಅಡಿಯಲ್ಲಿ ಕಷ್ಟಪಟ್ಟು ಕೆಲಸ ಮಾಡುತ್ತಾರೆ. ಅಂತಿಮವಾಗಿ ಅವುಗಳನ್ನು ಶುದ್ಧ ನೀರಿಗೆ ತರುವ ಸಮಯ. ನಾವು ಈ ಅನುಮಾನಾಸ್ಪದ ಪ್ರಕಾರಗಳೊಂದಿಗೆ ವ್ಯವಹರಿಸೋಣ.

PostgreSQL ನಲ್ಲಿ ಡೇಟಾ ಟೈಪಿಂಗ್, ಅದರ ಎಲ್ಲಾ ತರ್ಕಗಳಿಗೆ, ಕೆಲವೊಮ್ಮೆ ವಿಚಿತ್ರವಾದ ಆಶ್ಚರ್ಯಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಲೇಖನದಲ್ಲಿ ನಾವು ಅವರ ಕೆಲವು ಚಮತ್ಕಾರಗಳನ್ನು ಸ್ಪಷ್ಟಪಡಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತೇವೆ, ಅವರ ವಿಚಿತ್ರ ನಡವಳಿಕೆಯ ಕಾರಣವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಮತ್ತು ದೈನಂದಿನ ಅಭ್ಯಾಸದಲ್ಲಿ ಸಮಸ್ಯೆಗಳನ್ನು ಹೇಗೆ ಎದುರಿಸಬಾರದು ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸುತ್ತೇವೆ. ಸತ್ಯವನ್ನು ಹೇಳಲು, ನಾನು ಈ ಲೇಖನವನ್ನು ನನಗಾಗಿ ಒಂದು ರೀತಿಯ ಉಲ್ಲೇಖ ಪುಸ್ತಕವಾಗಿ ಸಂಗ್ರಹಿಸಿದ್ದೇನೆ, ವಿವಾದಾತ್ಮಕ ಪ್ರಕರಣಗಳಲ್ಲಿ ಸುಲಭವಾಗಿ ಉಲ್ಲೇಖಿಸಬಹುದಾದ ಉಲ್ಲೇಖ ಪುಸ್ತಕವಾಗಿದೆ. ಆದ್ದರಿಂದ, ಅನುಮಾನಾಸ್ಪದ ಪ್ರಕಾರಗಳಿಂದ ಹೊಸ ಆಶ್ಚರ್ಯಗಳನ್ನು ಕಂಡುಹಿಡಿಯುವುದರಿಂದ ಅದನ್ನು ಮರುಪೂರಣಗೊಳಿಸಲಾಗುತ್ತದೆ. ಆದ್ದರಿಂದ, ಹೋಗೋಣ, ಓ ದಣಿವರಿಯದ ಡೇಟಾಬೇಸ್ ಟ್ರ್ಯಾಕರ್‌ಗಳು!

ದಾಖಲೆ ಸಂಖ್ಯೆ ಒಂದು. ನೈಜ/ಡಬಲ್ ನಿಖರತೆ/ಸಂಖ್ಯೆ/ಹಣ

ನಡವಳಿಕೆಯಲ್ಲಿನ ಆಶ್ಚರ್ಯಗಳ ವಿಷಯದಲ್ಲಿ ಸಂಖ್ಯಾ ಪ್ರಕಾರಗಳು ಕಡಿಮೆ ಸಮಸ್ಯಾತ್ಮಕವಾಗಿವೆ ಎಂದು ತೋರುತ್ತದೆ. ಆದರೆ ಅದು ಹೇಗೆ ಇರಲಿ. ಆದ್ದರಿಂದ ಅವರೊಂದಿಗೆ ಪ್ರಾರಂಭಿಸೋಣ. ಆದ್ದರಿಂದ…

ಎಣಿಸುವುದು ಹೇಗೆಂದು ಮರೆತುಹೋಗಿದೆ

SELECT 0.1::real = 0.1

?column?
boolean
---------
f

ಏನು ವಿಷಯ? ಸಮಸ್ಯೆಯೆಂದರೆ PostgreSQL ಟೈಪ್ ಮಾಡದ ಸ್ಥಿರ 0.1 ಅನ್ನು ಡಬಲ್ ನಿಖರತೆಗೆ ಪರಿವರ್ತಿಸುತ್ತದೆ ಮತ್ತು ಅದನ್ನು ನೈಜ ಪ್ರಕಾರದ 0.1 ನೊಂದಿಗೆ ಹೋಲಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ಮತ್ತು ಇವು ಸಂಪೂರ್ಣವಾಗಿ ವಿಭಿನ್ನ ಅರ್ಥಗಳಾಗಿವೆ! ಯಂತ್ರ ಸ್ಮರಣೆಯಲ್ಲಿ ನೈಜ ಸಂಖ್ಯೆಗಳನ್ನು ಪ್ರತಿನಿಧಿಸುವುದು ಕಲ್ಪನೆ. 0.1 ಅನ್ನು ಸೀಮಿತ ಬೈನರಿ ಭಾಗವಾಗಿ ಪ್ರತಿನಿಧಿಸಲಾಗುವುದಿಲ್ಲ (ಬೈನರಿಯಲ್ಲಿ ಅದು 0.0 (0011) ಆಗಿರುತ್ತದೆ), ವಿಭಿನ್ನ ಬಿಟ್ ಆಳಗಳನ್ನು ಹೊಂದಿರುವ ಸಂಖ್ಯೆಗಳು ವಿಭಿನ್ನವಾಗಿರುತ್ತದೆ, ಆದ್ದರಿಂದ ಅವು ಸಮಾನವಾಗಿರುವುದಿಲ್ಲ. ಸಾಮಾನ್ಯವಾಗಿ ಹೇಳುವುದಾದರೆ, ಇದು ಪ್ರತ್ಯೇಕ ಲೇಖನದ ವಿಷಯವಾಗಿದೆ; ನಾನು ಇಲ್ಲಿ ಹೆಚ್ಚು ವಿವರವಾಗಿ ಬರೆಯುವುದಿಲ್ಲ.

ದೋಷ ಎಲ್ಲಿಂದ ಬರುತ್ತದೆ?

SELECT double precision(1)

ERROR:  syntax error at or near "("
LINE 1: SELECT double precision(1)
                               ^
********** Ошибка **********
ERROR: syntax error at or near "("
SQL-состояние: 42601
Символ: 24

PostgreSQL ಟೈಪ್ ಕ್ಯಾಸ್ಟಿಂಗ್‌ಗೆ ಕ್ರಿಯಾತ್ಮಕ ಸಂಕೇತವನ್ನು ಅನುಮತಿಸುತ್ತದೆ ಎಂದು ಅನೇಕ ಜನರಿಗೆ ತಿಳಿದಿದೆ. ಅಂದರೆ, ನೀವು 1:: int ಮಾತ್ರವಲ್ಲದೆ int (1) ಅನ್ನು ಸಹ ಬರೆಯಬಹುದು, ಅದು ಸಮಾನವಾಗಿರುತ್ತದೆ. ಆದರೆ ಹೆಸರುಗಳು ಹಲವಾರು ಪದಗಳನ್ನು ಒಳಗೊಂಡಿರುವ ಪ್ರಕಾರಗಳಿಗೆ ಅಲ್ಲ! ಆದ್ದರಿಂದ, ನೀವು ಕ್ರಿಯಾತ್ಮಕ ರೂಪದಲ್ಲಿ ಎರಡು ನಿಖರತೆಯ ಪ್ರಕಾರಕ್ಕೆ ಸಂಖ್ಯಾ ಮೌಲ್ಯವನ್ನು ಬಿತ್ತರಿಸಲು ಬಯಸಿದರೆ, ಈ ಪ್ರಕಾರದ float8 ನ ಅಲಿಯಾಸ್ ಅನ್ನು ಬಳಸಿ, ಅಂದರೆ, SELECT float8(1).

ಅನಂತಕ್ಕಿಂತ ದೊಡ್ಡದು ಯಾವುದು?

SELECT 'Infinity'::double precision < 'NaN'::double precision

?column?
boolean
---------
t

ಅದು ಹೇಗಿದೆ ನೋಡಿ! ಇದು ಅನಂತಕ್ಕಿಂತ ದೊಡ್ಡದಾಗಿದೆ ಎಂದು ತಿರುಗುತ್ತದೆ ಮತ್ತು ಅದು NaN! ಅದೇ ಸಮಯದಲ್ಲಿ, PostgreSQL ದಸ್ತಾವೇಜನ್ನು ಪ್ರಾಮಾಣಿಕ ಕಣ್ಣುಗಳಿಂದ ನಮ್ಮನ್ನು ನೋಡುತ್ತದೆ ಮತ್ತು NaN ನಿಸ್ಸಂಶಯವಾಗಿ ಯಾವುದೇ ಇತರ ಸಂಖ್ಯೆಗಳಿಗಿಂತ ದೊಡ್ಡದಾಗಿದೆ ಎಂದು ಹೇಳುತ್ತದೆ ಮತ್ತು ಆದ್ದರಿಂದ, ಅನಂತತೆ. -NaN ಗೆ ವಿರುದ್ಧವೂ ನಿಜವಾಗಿದೆ. ಹಲೋ, ಗಣಿತ ಪ್ರೇಮಿಗಳು! ಆದರೆ ಇದೆಲ್ಲವೂ ನೈಜ ಸಂಖ್ಯೆಗಳ ಸಂದರ್ಭದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ನಾವು ನೆನಪಿನಲ್ಲಿಡಬೇಕು.

ಕಣ್ಣಿನ ಸುತ್ತುವಿಕೆ

SELECT round('2.5'::double precision)
     , round('2.5'::numeric)

      round      |  round
double precision | numeric
-----------------+---------
2                | 3

ಮೂಲದಿಂದ ಮತ್ತೊಂದು ಅನಿರೀಕ್ಷಿತ ಶುಭಾಶಯ. ಮತ್ತೊಮ್ಮೆ, ಡಬಲ್ ನಿಖರತೆ ಮತ್ತು ಸಂಖ್ಯಾ ಪ್ರಕಾರಗಳು ವಿಭಿನ್ನ ಪೂರ್ಣಾಂಕದ ಪರಿಣಾಮಗಳನ್ನು ಹೊಂದಿವೆ ಎಂಬುದನ್ನು ನೆನಪಿಡಿ. ಸಂಖ್ಯಾತ್ಮಕವಾಗಿ - ಸಾಮಾನ್ಯವಾದದ್ದು, 0,5 ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದಾಗ ಮತ್ತು ಡಬಲ್ ನಿಖರತೆಗಾಗಿ - 0,5 ಅನ್ನು ಹತ್ತಿರದ ಸಮ ಪೂರ್ಣಾಂಕದ ಕಡೆಗೆ ದುಂಡಾಗಿರುತ್ತದೆ.

ಹಣವು ವಿಶೇಷವಾದದ್ದು

SELECT '10'::money::float8

ERROR:  cannot cast type money to double precision
LINE 1: SELECT '10'::money::float8
                          ^
********** Ошибка **********
ERROR: cannot cast type money to double precision
SQL-состояние: 42846
Символ: 19

PostgreSQL ಪ್ರಕಾರ, ಹಣವು ನೈಜ ಸಂಖ್ಯೆಯಲ್ಲ. ಕೆಲವು ವ್ಯಕ್ತಿಗಳ ಪ್ರಕಾರ ಕೂಡ. ಹಣದ ಪ್ರಕಾರವನ್ನು ಬಿತ್ತರಿಸುವುದು ಸಂಖ್ಯಾ ಪ್ರಕಾರಕ್ಕೆ ಮಾತ್ರ ಸಾಧ್ಯ ಎಂಬುದನ್ನು ನಾವು ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊಳ್ಳಬೇಕು, ಹಾಗೆಯೇ ಸಂಖ್ಯಾ ಪ್ರಕಾರವನ್ನು ಹಣದ ಪ್ರಕಾರಕ್ಕೆ ಬಿತ್ತರಿಸಬಹುದು. ಆದರೆ ಈಗ ನೀವು ನಿಮ್ಮ ಹೃದಯ ಬಯಸಿದಂತೆ ಅದರೊಂದಿಗೆ ಆಡಬಹುದು. ಆದರೆ ಅದೇ ಹಣ ಆಗುವುದಿಲ್ಲ.

ಸಣ್ಣ ಮತ್ತು ಅನುಕ್ರಮ ಉತ್ಪಾದನೆ

SELECT *
  FROM generate_series(1::smallint, 5::smallint, 1::smallint)

ERROR:  function generate_series(smallint, smallint, smallint) is not unique
LINE 2:   FROM generate_series(1::smallint, 5::smallint, 1::smallint...
               ^
HINT:  Could not choose a best candidate function. You might need to add explicit type casts.
********** Ошибка **********
ERROR: function generate_series(smallint, smallint, smallint) is not unique
SQL-состояние: 42725
Подсказка: Could not choose a best candidate function. You might need to add explicit type casts.
Символ: 18

PostgreSQL ಟ್ರೈಫಲ್‌ಗಳಲ್ಲಿ ಸಮಯವನ್ನು ವ್ಯರ್ಥ ಮಾಡಲು ಇಷ್ಟಪಡುವುದಿಲ್ಲ. ಸ್ಮಾಲ್ಇಂಟ್ ಅನ್ನು ಆಧರಿಸಿದ ಈ ಅನುಕ್ರಮಗಳು ಯಾವುವು? ಇಂಟ್, ಕಡಿಮೆ ಇಲ್ಲ! ಆದ್ದರಿಂದ, ಮೇಲಿನ ಪ್ರಶ್ನೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಪ್ರಯತ್ನಿಸುವಾಗ, ಡೇಟಾಬೇಸ್ ಸ್ಮಾಲ್‌ಇಂಟ್ ಅನ್ನು ಬೇರೆ ಕೆಲವು ಪೂರ್ಣಾಂಕ ಪ್ರಕಾರಕ್ಕೆ ಬಿತ್ತರಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ ಮತ್ತು ಅಂತಹ ಹಲವಾರು ಕ್ಯಾಸ್ಟ್‌ಗಳು ಇರಬಹುದೆಂದು ನೋಡುತ್ತದೆ. ಯಾವ ಪಾತ್ರವನ್ನು ಆಯ್ಕೆ ಮಾಡಬೇಕು? ಅವಳು ಇದನ್ನು ನಿರ್ಧರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ ಮತ್ತು ಆದ್ದರಿಂದ ದೋಷದಿಂದ ಕ್ರ್ಯಾಶ್ ಆಗುತ್ತಾಳೆ.

ಫೈಲ್ ಸಂಖ್ಯೆ ಎರಡು. "ಚಾರ್"/ಚಾರ್/ವರ್ಚಾರ್/ಪಠ್ಯ

ಅಕ್ಷರ ಪ್ರಕಾರಗಳಲ್ಲಿ ಹಲವಾರು ವಿಚಿತ್ರತೆಗಳು ಸಹ ಇರುತ್ತವೆ. ಅವರನ್ನೂ ತಿಳಿದುಕೊಳ್ಳೋಣ.

ಇವು ಯಾವ ರೀತಿಯ ತಂತ್ರಗಳು?

SELECT 'ПЕТЯ'::"char"
     , 'ПЕТЯ'::"char"::bytea
     , 'ПЕТЯ'::char
     , 'ПЕТЯ'::char::bytea

 char  | bytea |    bpchar    | bytea
"char" | bytea | character(1) | bytea
-------+-------+--------------+--------
 ╨     | xd0  | П            | xd09f

ಇದು ಯಾವ ರೀತಿಯ "ಚಾರ್", ಇದು ಯಾವ ರೀತಿಯ ಕೋಡಂಗಿ? ನಮಗೆ ಅದು ಅಗತ್ಯವಿಲ್ಲ ... ಏಕೆಂದರೆ ಅದು ಉಲ್ಲೇಖಗಳಲ್ಲಿದ್ದರೂ ಸಹ ಸಾಮಾನ್ಯ ಚಾರ್ ಎಂದು ನಟಿಸುತ್ತದೆ. ಮತ್ತು ಇದು ಸಾಮಾನ್ಯ ಚಾರ್‌ನಿಂದ ಭಿನ್ನವಾಗಿದೆ, ಇದು ಉಲ್ಲೇಖಗಳಿಲ್ಲದೆ, ಇದು ಸ್ಟ್ರಿಂಗ್ ಪ್ರಾತಿನಿಧ್ಯದ ಮೊದಲ ಬೈಟ್ ಅನ್ನು ಮಾತ್ರ ಔಟ್‌ಪುಟ್ ಮಾಡುತ್ತದೆ, ಆದರೆ ಸಾಮಾನ್ಯ ಚಾರ್ ಮೊದಲ ಅಕ್ಷರವನ್ನು ನೀಡುತ್ತದೆ. ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ, ಮೊದಲ ಅಕ್ಷರವು ಪಿ ಅಕ್ಷರವಾಗಿದೆ, ಇದು ಯುನಿಕೋಡ್ ಪ್ರಾತಿನಿಧ್ಯದಲ್ಲಿ 2 ಬೈಟ್‌ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ, ಫಲಿತಾಂಶವನ್ನು ಬೈಟಿ ಪ್ರಕಾರಕ್ಕೆ ಪರಿವರ್ತಿಸುವ ಮೂಲಕ ಸಾಕ್ಷಿಯಾಗಿದೆ. ಮತ್ತು "ಚಾರ್" ಪ್ರಕಾರವು ಈ ಯುನಿಕೋಡ್ ಪ್ರಾತಿನಿಧ್ಯದ ಮೊದಲ ಬೈಟ್ ಅನ್ನು ಮಾತ್ರ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ. ಹಾಗಾದರೆ ಈ ಪ್ರಕಾರ ಏಕೆ ಬೇಕು? ವಿಶೇಷ ಅಗತ್ಯಗಳಿಗಾಗಿ ಬಳಸಲಾಗುವ ವಿಶೇಷ ಪ್ರಕಾರವಾಗಿದೆ ಎಂದು PostgreSQL ದಸ್ತಾವೇಜನ್ನು ಹೇಳುತ್ತದೆ. ಆದ್ದರಿಂದ ನಮಗೆ ಇದು ಅಗತ್ಯವಿರುವುದಿಲ್ಲ. ಆದರೆ ಅವನ ಕಣ್ಣುಗಳನ್ನು ನೋಡಿ ಮತ್ತು ಅವನ ವಿಶೇಷ ನಡವಳಿಕೆಯೊಂದಿಗೆ ನೀವು ಅವನನ್ನು ಭೇಟಿಯಾದಾಗ ನೀವು ತಪ್ಪಾಗುವುದಿಲ್ಲ.

ಹೆಚ್ಚುವರಿ ಸ್ಥಳಗಳು. ಕಣ್ಣಿಗೆ ಕಾಣದವ ಮನಸ್ಸಿಗೆ ಕಾಣನು

SELECT 'abc   '::char(6)::bytea
     , 'abc   '::char(6)::varchar(6)::bytea
     , 'abc   '::varchar(6)::bytea

     bytea     |   bytea  |     bytea
     bytea     |   bytea  |     bytea
---------------+----------+----------------
x616263202020 | x616263 | x616263202020

ಕೊಟ್ಟಿರುವ ಉದಾಹರಣೆಯನ್ನು ಗಮನಿಸಿ. ನಾನು ಎಲ್ಲಾ ಫಲಿತಾಂಶಗಳನ್ನು ಬೈಟಿ ಪ್ರಕಾರಕ್ಕೆ ವಿಶೇಷವಾಗಿ ಪರಿವರ್ತಿಸಿದ್ದೇನೆ, ಇದರಿಂದ ಅಲ್ಲಿ ಏನಿದೆ ಎಂಬುದು ಸ್ಪಷ್ಟವಾಗಿ ಗೋಚರಿಸುತ್ತದೆ. ವರ್ಚಾರ್(6) ಗೆ ಬಿತ್ತರಿಸಿದ ನಂತರ ಟ್ರೇಲಿಂಗ್ ಸ್ಪೇಸ್‌ಗಳು ಎಲ್ಲಿವೆ? ದಸ್ತಾವೇಜನ್ನು ಸಂಕ್ಷಿಪ್ತವಾಗಿ ಹೇಳುತ್ತದೆ: "ಮತ್ತೊಂದು ಅಕ್ಷರ ಪ್ರಕಾರಕ್ಕೆ ಪಾತ್ರದ ಮೌಲ್ಯವನ್ನು ಬಿತ್ತರಿಸಿದಾಗ, ಟ್ರೇಲಿಂಗ್ ವೈಟ್‌ಸ್ಪೇಸ್ ಅನ್ನು ತಿರಸ್ಕರಿಸಲಾಗುತ್ತದೆ." ಈ ಅಸಹ್ಯವನ್ನು ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊಳ್ಳಬೇಕು. ಮತ್ತು ಉಲ್ಲೇಖಿತ ಸ್ಟ್ರಿಂಗ್ ಸ್ಥಿರಾಂಕವನ್ನು ನೇರವಾಗಿ varchar(6) ಟೈಪ್ ಮಾಡಲು ಬಿತ್ತರಿಸಿದರೆ, ಟ್ರೇಲಿಂಗ್ ಸ್ಪೇಸ್‌ಗಳನ್ನು ಸಂರಕ್ಷಿಸಲಾಗಿದೆ ಎಂಬುದನ್ನು ಗಮನಿಸಿ. ಅಂತಹ ಪವಾಡಗಳು.

ಫೈಲ್ ಸಂಖ್ಯೆ ಮೂರು. json/jsonb

JSON ತನ್ನದೇ ಆದ ಜೀವನವನ್ನು ನಡೆಸುವ ಪ್ರತ್ಯೇಕ ರಚನೆಯಾಗಿದೆ. ಆದ್ದರಿಂದ, ಅದರ ಘಟಕಗಳು ಮತ್ತು PostgreSQL ನ ಘಟಕಗಳು ಸ್ವಲ್ಪ ವಿಭಿನ್ನವಾಗಿವೆ. ಉದಾಹರಣೆಗಳು ಇಲ್ಲಿವೆ.

ಜಾನ್ಸನ್ ಮತ್ತು ಜಾನ್ಸನ್. ವ್ಯತ್ಯಾಸವನ್ನು ಅನುಭವಿಸಿ

SELECT 'null'::jsonb IS NULL

?column?
boolean
---------
f

ವಿಷಯವೆಂದರೆ JSON ತನ್ನದೇ ಆದ ಶೂನ್ಯ ಅಸ್ತಿತ್ವವನ್ನು ಹೊಂದಿದೆ, ಇದು PostgreSQL ನಲ್ಲಿ NULL ನ ಅನಲಾಗ್ ಅಲ್ಲ. ಅದೇ ಸಮಯದಲ್ಲಿ, JSON ಆಬ್ಜೆಕ್ಟ್ ಸ್ವತಃ NULL ಮೌಲ್ಯವನ್ನು ಹೊಂದಿರಬಹುದು, ಆದ್ದರಿಂದ SELECT null::jsonb IS NULL (ಏಕ ಉಲ್ಲೇಖಗಳ ಅನುಪಸ್ಥಿತಿಯನ್ನು ಗಮನಿಸಿ) ಎಂಬ ಅಭಿವ್ಯಕ್ತಿ ಈ ಬಾರಿ ನಿಜ ಎಂದು ಹಿಂತಿರುಗಿಸುತ್ತದೆ.

ಒಂದು ಅಕ್ಷರವು ಎಲ್ಲವನ್ನೂ ಬದಲಾಯಿಸುತ್ತದೆ

SELECT '{"1": [1, 2, 3], "2": [4, 5, 6], "1": [7, 8, 9]}'::json

                     json
                     json
------------------------------------------------
{"1": [1, 2, 3], "2": [4, 5, 6], "1": [7, 8, 9]}

---

SELECT '{"1": [1, 2, 3], "2": [4, 5, 6], "1": [7, 8, 9]}'::jsonb

             jsonb
             jsonb
--------------------------------
{"1": [7, 8, 9], "2": [4, 5, 6]}

ವಿಷಯವೆಂದರೆ json ಮತ್ತು jsonb ಸಂಪೂರ್ಣವಾಗಿ ವಿಭಿನ್ನ ರಚನೆಗಳು. json ನಲ್ಲಿ, ವಸ್ತುವನ್ನು ಹಾಗೆಯೇ ಸಂಗ್ರಹಿಸಲಾಗಿದೆ, ಮತ್ತು jsonb ನಲ್ಲಿ ಇದನ್ನು ಈಗಾಗಲೇ ಪಾರ್ಸ್ಡ್, ಇಂಡೆಕ್ಸ್ಡ್ ರಚನೆಯ ರೂಪದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿದೆ. ಅದಕ್ಕಾಗಿಯೇ ಎರಡನೆಯ ಪ್ರಕರಣದಲ್ಲಿ, ವಸ್ತುವಿನ ಮೌಲ್ಯವನ್ನು ಕೀ 1 ರಿಂದ [1, 2, 3] ರಿಂದ [7, 8, 9] ಗೆ ಬದಲಾಯಿಸಲಾಯಿತು, ಅದು ಅದೇ ಕೀಲಿಯೊಂದಿಗೆ ರಚನೆಗೆ ಕೊನೆಯಲ್ಲಿ ಬಂದಿತು.

ನಿಮ್ಮ ಮುಖದಿಂದ ನೀರನ್ನು ಕುಡಿಯಬೇಡಿ

SELECT '{"reading": 1.230e-5}'::jsonb
     , '{"reading": 1.230e-5}'::json

          jsonb         |         json
          jsonb         |         json
------------------------+----------------------
{"reading": 0.00001230} | {"reading": 1.230e-5}

PostgreSQL ಅದರ JSONB ಅನುಷ್ಠಾನದಲ್ಲಿ ನೈಜ ಸಂಖ್ಯೆಗಳ ಫಾರ್ಮ್ಯಾಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ, ಅವುಗಳನ್ನು ಶಾಸ್ತ್ರೀಯ ರೂಪಕ್ಕೆ ತರುತ್ತದೆ. JSON ಪ್ರಕಾರಕ್ಕೆ ಇದು ಸಂಭವಿಸುವುದಿಲ್ಲ. ಸ್ವಲ್ಪ ವಿಚಿತ್ರ, ಆದರೆ ಅವನು ಹೇಳಿದ್ದು ಸರಿ.

ಫೈಲ್ ಸಂಖ್ಯೆ ನಾಲ್ಕು. ದಿನಾಂಕ/ಸಮಯ/ಸಮಯಮುದ್ರೆ

ದಿನಾಂಕ/ಸಮಯದ ಪ್ರಕಾರಗಳೊಂದಿಗೆ ಕೆಲವು ವಿಚಿತ್ರತೆಗಳೂ ಇವೆ. ಅವುಗಳನ್ನು ನೋಡೋಣ. ಸಮಯ ವಲಯಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವ ಮೂಲತತ್ವವನ್ನು ನೀವು ಚೆನ್ನಾಗಿ ಅರ್ಥಮಾಡಿಕೊಂಡರೆ ಕೆಲವು ನಡವಳಿಕೆಯ ವೈಶಿಷ್ಟ್ಯಗಳು ಸ್ಪಷ್ಟವಾಗುತ್ತವೆ ಎಂದು ನಾನು ಈಗಿನಿಂದಲೇ ಕಾಯ್ದಿರಿಸುತ್ತೇನೆ. ಆದರೆ ಇದು ಪ್ರತ್ಯೇಕ ಲೇಖನಕ್ಕೆ ಒಂದು ವಿಷಯವಾಗಿದೆ.

ನನ್ನ ನಿಮ್ಮದು ಅರ್ಥವಾಗುತ್ತಿಲ್ಲ

SELECT '08-Jan-99'::date

ERROR:  date/time field value out of range: "08-Jan-99"
LINE 1: SELECT '08-Jan-99'::date
               ^
HINT:  Perhaps you need a different "datestyle" setting.
********** Ошибка **********
ERROR: date/time field value out of range: "08-Jan-99"
SQL-состояние: 22008
Подсказка: Perhaps you need a different "datestyle" setting.
Символ: 8

ಇಲ್ಲಿ ಏನು ಗ್ರಹಿಸಲಾಗದು ಎಂದು ತೋರುತ್ತದೆ? ಆದರೆ ಡೇಟಾಬೇಸ್‌ಗೆ ನಾವು ಇಲ್ಲಿ ಮೊದಲ ಸ್ಥಾನದಲ್ಲಿರುವುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲಾಗಿಲ್ಲ-ವರ್ಷ ಅಥವಾ ದಿನ? ಮತ್ತು ಇದು ಜನವರಿ 99, 2008 ಎಂದು ಅವಳು ನಿರ್ಧರಿಸುತ್ತಾಳೆ, ಅದು ಅವಳ ಮನಸ್ಸನ್ನು ಸ್ಫೋಟಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯವಾಗಿ ಹೇಳುವುದಾದರೆ, ಪಠ್ಯ ಸ್ವರೂಪದಲ್ಲಿ ದಿನಾಂಕಗಳನ್ನು ರವಾನಿಸುವಾಗ, ಡೇಟಾಬೇಸ್ ಅವುಗಳನ್ನು ಎಷ್ಟು ಸರಿಯಾಗಿ ಗುರುತಿಸಿದೆ ಎಂಬುದನ್ನು ನೀವು ಬಹಳ ಎಚ್ಚರಿಕೆಯಿಂದ ಪರಿಶೀಲಿಸಬೇಕು (ನಿರ್ದಿಷ್ಟವಾಗಿ, SHOW ಡೇಟ್‌ಸ್ಟೈಲ್ ಆಜ್ಞೆಯೊಂದಿಗೆ ಡೇಟ್‌ಸ್ಟೈಲ್ ನಿಯತಾಂಕವನ್ನು ವಿಶ್ಲೇಷಿಸಿ), ಏಕೆಂದರೆ ಈ ವಿಷಯದಲ್ಲಿ ಅಸ್ಪಷ್ಟತೆಗಳು ತುಂಬಾ ದುಬಾರಿಯಾಗಬಹುದು.

ನೀವು ಇದನ್ನು ಎಲ್ಲಿಂದ ಪಡೆದುಕೊಂಡಿದ್ದೀರಿ?

SELECT '04:05 Europe/Moscow'::time

ERROR:  invalid input syntax for type time: "04:05 Europe/Moscow"
LINE 1: SELECT '04:05 Europe/Moscow'::time
               ^
********** Ошибка **********
ERROR: invalid input syntax for type time: "04:05 Europe/Moscow"
SQL-состояние: 22007
Символ: 8

ಡೇಟಾಬೇಸ್ ಸ್ಪಷ್ಟವಾಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಿದ ಸಮಯವನ್ನು ಏಕೆ ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ? ಏಕೆಂದರೆ ಸಮಯ ವಲಯವು ಸಂಕ್ಷೇಪಣವನ್ನು ಹೊಂದಿಲ್ಲ, ಆದರೆ ಪೂರ್ಣ ಹೆಸರು, ಇದು ದಿನಾಂಕದ ಸಂದರ್ಭದಲ್ಲಿ ಮಾತ್ರ ಅರ್ಥಪೂರ್ಣವಾಗಿದೆ, ಏಕೆಂದರೆ ಇದು ಸಮಯ ವಲಯ ಬದಲಾವಣೆಗಳ ಇತಿಹಾಸವನ್ನು ಗಣನೆಗೆ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ ಮತ್ತು ದಿನಾಂಕವಿಲ್ಲದೆ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ. ಮತ್ತು ಸಮಯದ ರೇಖೆಯ ಮಾತುಗಳು ಪ್ರಶ್ನೆಗಳನ್ನು ಹುಟ್ಟುಹಾಕುತ್ತದೆ - ಪ್ರೋಗ್ರಾಮರ್ ನಿಜವಾಗಿಯೂ ಏನು ಅರ್ಥ? ಆದ್ದರಿಂದ, ನೀವು ಅದನ್ನು ನೋಡಿದರೆ ಎಲ್ಲವೂ ಇಲ್ಲಿ ತಾರ್ಕಿಕವಾಗಿದೆ.

ಅವನಿಗೇನಾಗಿದೆ?

ಪರಿಸ್ಥಿತಿಯನ್ನು ಊಹಿಸಿ. ನಿಮ್ಮ ಟೇಬಲ್‌ನಲ್ಲಿ ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್ಟ್ಜ್ ಟೈಪ್‌ನೊಂದಿಗೆ ನೀವು ಕ್ಷೇತ್ರವನ್ನು ಹೊಂದಿದ್ದೀರಿ. ನೀವು ಅದನ್ನು ಸೂಚಿಕೆ ಮಾಡಲು ಬಯಸುತ್ತೀರಿ. ಆದರೆ ಈ ಕ್ಷೇತ್ರದಲ್ಲಿ ಸೂಚ್ಯಂಕವನ್ನು ನಿರ್ಮಿಸುವುದು ಅದರ ಹೆಚ್ಚಿನ ಆಯ್ಕೆಯಿಂದಾಗಿ ಯಾವಾಗಲೂ ಸಮರ್ಥಿಸುವುದಿಲ್ಲ ಎಂದು ನೀವು ಅರ್ಥಮಾಡಿಕೊಂಡಿದ್ದೀರಿ (ಈ ಪ್ರಕಾರದ ಬಹುತೇಕ ಎಲ್ಲಾ ಮೌಲ್ಯಗಳು ಅನನ್ಯವಾಗಿರುತ್ತವೆ). ಆದ್ದರಿಂದ ದಿನಾಂಕಕ್ಕೆ ಪ್ರಕಾರವನ್ನು ಬಿತ್ತರಿಸುವ ಮೂಲಕ ಸೂಚ್ಯಂಕದ ಆಯ್ಕೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಲು ನೀವು ನಿರ್ಧರಿಸುತ್ತೀರಿ. ಮತ್ತು ನೀವು ಆಶ್ಚರ್ಯವನ್ನು ಪಡೆಯುತ್ತೀರಿ:

CREATE INDEX "iIdent-DateLastUpdate"
  ON public."Ident" USING btree
  (("DTLastUpdate"::date));

ERROR:  functions in index expression must be marked IMMUTABLE
********** Ошибка **********
ERROR: functions in index expression must be marked IMMUTABLE
SQL-состояние: 42P17

ಏನು ವಿಷಯ? ಸತ್ಯವೆಂದರೆ ಟೈಮ್‌ಸ್ಟ್ಯಾಂಪ್ಟ್ಜ್ ಪ್ರಕಾರವನ್ನು ದಿನಾಂಕ ಪ್ರಕಾರಕ್ಕೆ ಬಿತ್ತರಿಸಲು, ಟೈಮ್‌ಝೋನ್ ಸಿಸ್ಟಮ್ ಪ್ಯಾರಾಮೀಟರ್‌ನ ಮೌಲ್ಯವನ್ನು ಬಳಸಲಾಗುತ್ತದೆ, ಇದು ಕಸ್ಟಮ್ ಪ್ಯಾರಾಮೀಟರ್‌ನ ಮೇಲೆ ಪ್ರಕಾರದ ಪರಿವರ್ತನೆ ಕಾರ್ಯವನ್ನು ಅವಲಂಬಿಸಿದೆ, ಅಂದರೆ. ಬಾಷ್ಪಶೀಲ. ಅಂತಹ ಕಾರ್ಯಗಳನ್ನು ಸೂಚ್ಯಂಕದಲ್ಲಿ ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ. ಈ ಸಂದರ್ಭದಲ್ಲಿ, ಪ್ರಕಾರದ ಎರಕಹೊಯ್ದವನ್ನು ಯಾವ ಸಮಯ ವಲಯದಲ್ಲಿ ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ನೀವು ಸ್ಪಷ್ಟವಾಗಿ ಸೂಚಿಸಬೇಕು.

ಈಗ ಆಗಿಲ್ಲ ಈಗ ಕೂಡ

ಸಮಯ ವಲಯವನ್ನು ಗಣನೆಗೆ ತೆಗೆದುಕೊಂಡು ಪ್ರಸ್ತುತ ದಿನಾಂಕ/ಸಮಯವನ್ನು ಹಿಂತಿರುಗಿಸಲು ನಾವು ಈಗ () ಬಳಸಲಾಗುತ್ತದೆ. ಆದರೆ ಈ ಕೆಳಗಿನ ಪ್ರಶ್ನೆಗಳನ್ನು ನೋಡಿ:

START TRANSACTION;
SELECT now();

            now
  timestamp with time zone
-----------------------------
2019-11-26 13:13:04.271419+03

...

SELECT now();

            now
  timestamp with time zone
-----------------------------
2019-11-26 13:13:04.271419+03

...

SELECT now();

            now
  timestamp with time zone
-----------------------------
2019-11-26 13:13:04.271419+03

COMMIT;

ಹಿಂದಿನ ವಿನಂತಿಯಿಂದ ಎಷ್ಟು ಸಮಯ ಕಳೆದರೂ ದಿನಾಂಕ/ಸಮಯವನ್ನು ಅದೇ ರೀತಿ ಹಿಂತಿರುಗಿಸಲಾಗುತ್ತದೆ! ಏನು ವಿಷಯ? ಸತ್ಯವೆಂದರೆ ಈಗ () ಪ್ರಸ್ತುತ ಸಮಯವಲ್ಲ, ಆದರೆ ಪ್ರಸ್ತುತ ವಹಿವಾಟಿನ ಪ್ರಾರಂಭದ ಸಮಯ. ಆದ್ದರಿಂದ, ವಹಿವಾಟಿನೊಳಗೆ ಅದು ಬದಲಾಗುವುದಿಲ್ಲ. ವಹಿವಾಟಿನ ವ್ಯಾಪ್ತಿಯ ಹೊರಗೆ ಪ್ರಾರಂಭಿಸಲಾದ ಯಾವುದೇ ಪ್ರಶ್ನೆಯು ವ್ಯವಹಾರದಲ್ಲಿ ಸೂಚ್ಯವಾಗಿ ಸುತ್ತುತ್ತದೆ, ಅದಕ್ಕಾಗಿಯೇ ಸರಳವಾದ SELECT ಮೂಲಕ ಸಮಯವನ್ನು ಹಿಂತಿರುಗಿಸಿರುವುದನ್ನು ನಾವು ಗಮನಿಸುವುದಿಲ್ಲ (); ವಾಸ್ತವವಾಗಿ, ಪ್ರಸ್ತುತ ಅಲ್ಲ... ನೀವು ಪ್ರಾಮಾಣಿಕ ಪ್ರಸ್ತುತ ಸಮಯವನ್ನು ಪಡೆಯಲು ಬಯಸಿದರೆ, ನೀವು clock_timestamp() ಕಾರ್ಯವನ್ನು ಬಳಸಬೇಕಾಗುತ್ತದೆ.

ಫೈಲ್ ಸಂಖ್ಯೆ ಐದು. ಸ್ವಲ್ಪ

ಸ್ವಲ್ಪ ವಿಚಿತ್ರ

SELECT '111'::bit(4)

 bit
bit(4)
------
1110

ಪ್ರಕಾರ ವಿಸ್ತರಣೆಯ ಸಂದರ್ಭದಲ್ಲಿ ಬಿಟ್‌ಗಳನ್ನು ಯಾವ ಕಡೆ ಸೇರಿಸಬೇಕು? ಇದು ಎಡಭಾಗದಲ್ಲಿದೆ ಎಂದು ತೋರುತ್ತದೆ. ಆದರೆ ಬೇಸ್ ಮಾತ್ರ ಈ ವಿಷಯದಲ್ಲಿ ವಿಭಿನ್ನ ಅಭಿಪ್ರಾಯವನ್ನು ಹೊಂದಿದೆ. ಜಾಗರೂಕರಾಗಿರಿ: ಪ್ರಕಾರವನ್ನು ಬಿತ್ತರಿಸುವಾಗ ಅಂಕೆಗಳ ಸಂಖ್ಯೆ ಹೊಂದಿಕೆಯಾಗದಿದ್ದರೆ, ನೀವು ಬಯಸಿದ್ದನ್ನು ನೀವು ಪಡೆಯುವುದಿಲ್ಲ. ಬಿಟ್‌ಗಳನ್ನು ಬಲಕ್ಕೆ ಸೇರಿಸುವುದು ಮತ್ತು ಬಿಟ್‌ಗಳನ್ನು ಟ್ರಿಮ್ ಮಾಡುವುದು ಎರಡಕ್ಕೂ ಇದು ಅನ್ವಯಿಸುತ್ತದೆ. ಹಾಗೆಯೇ ಬಲಭಾಗದಲ್ಲಿ...

ಫೈಲ್ ಸಂಖ್ಯೆ ಆರು. ಅರೇಗಳು

NULL ಕೂಡ ಗುಂಡು ಹಾರಿಸಲಿಲ್ಲ

SELECT ARRAY[1, 2] || NULL

?column?
integer[]
---------
{1,2}

SQL ನಲ್ಲಿ ಬೆಳೆದ ಸಾಮಾನ್ಯ ಜನರು, ಈ ಅಭಿವ್ಯಕ್ತಿಯ ಫಲಿತಾಂಶವು NULL ಆಗಿರುತ್ತದೆ ಎಂದು ನಾವು ನಿರೀಕ್ಷಿಸುತ್ತೇವೆ. ಆದರೆ ಅಲ್ಲಿ ಇರಲಿಲ್ಲ. ಒಂದು ಶ್ರೇಣಿಯನ್ನು ಹಿಂತಿರುಗಿಸಲಾಗಿದೆ. ಏಕೆ? ಏಕೆಂದರೆ ಈ ಸಂದರ್ಭದಲ್ಲಿ ಆಧಾರವು ಪೂರ್ಣಾಂಕ ಶ್ರೇಣಿಗೆ NULL ಅನ್ನು ಬಿತ್ತರಿಸುತ್ತದೆ ಮತ್ತು array_cat ಕಾರ್ಯವನ್ನು ಸೂಚ್ಯವಾಗಿ ಕರೆಯುತ್ತದೆ. ಆದರೆ ಈ "ಅರೇ ಕ್ಯಾಟ್" ಏಕೆ ಸರಣಿಯನ್ನು ಮರುಹೊಂದಿಸುವುದಿಲ್ಲ ಎಂಬುದು ಇನ್ನೂ ಅಸ್ಪಷ್ಟವಾಗಿದೆ. ಈ ನಡವಳಿಕೆಯನ್ನು ಸಹ ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊಳ್ಳಬೇಕು.

ಸಾರಾಂಶಗೊಳಿಸಿ. ಸಾಕಷ್ಟು ವಿಚಿತ್ರ ಸಂಗತಿಗಳಿವೆ. ಅವರಲ್ಲಿ ಹೆಚ್ಚಿನವರು, ಸ್ಪಷ್ಟವಾಗಿ ಅನುಚಿತ ವರ್ತನೆಯ ಬಗ್ಗೆ ಮಾತನಾಡುವಷ್ಟು ವಿಮರ್ಶಾತ್ಮಕವಾಗಿಲ್ಲ. ಮತ್ತು ಇತರವು ಬಳಕೆಯ ಸುಲಭತೆ ಅಥವಾ ಕೆಲವು ಸಂದರ್ಭಗಳಲ್ಲಿ ಅವುಗಳ ಅನ್ವಯದ ಆವರ್ತನದಿಂದ ವಿವರಿಸಲಾಗಿದೆ. ಆದರೆ ಅದೇ ಸಮಯದಲ್ಲಿ, ಅನೇಕ ಆಶ್ಚರ್ಯಗಳಿವೆ. ಆದ್ದರಿಂದ, ನೀವು ಅವರ ಬಗ್ಗೆ ತಿಳಿದುಕೊಳ್ಳಬೇಕು. ಯಾವುದೇ ಪ್ರಕಾರದ ನಡವಳಿಕೆಯಲ್ಲಿ ನೀವು ಬೇರೆ ಯಾವುದನ್ನಾದರೂ ವಿಚಿತ್ರ ಅಥವಾ ಅಸಾಮಾನ್ಯವೆಂದು ಕಂಡುಕೊಂಡರೆ, ಕಾಮೆಂಟ್‌ಗಳಲ್ಲಿ ಬರೆಯಿರಿ, ಅವುಗಳ ಮೇಲೆ ಲಭ್ಯವಿರುವ ದಾಖಲೆಗಳಿಗೆ ಸೇರಿಸಲು ನಾನು ಸಂತೋಷಪಡುತ್ತೇನೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ