Tipi suspettużi

M'hemm xejn suspettuż dwar id-dehra tagħhom. Barra minn hekk, huma saħansitra jidhru familjari għalik tajjeb u għal żmien twil. Imma dan biss sakemm tiċċekkjahom. Dan huwa fejn juru n-natura insidjuża tagħhom, jaħdmu kompletament differenti milli suppost stennejt. U xi drabi jagħmlu xi ħaġa li tagħmel ix-xagħar tiegħek fuq tarf - pereżempju, jitilfu d-dejta sigrieta fdata lilhom. Meta tikkonfrontahom, huma jsostnu li ma jafux lil xulxin, għalkemm fid-dell jaħdmu iebes taħt l-istess barnuża. Wasal iż-żmien li fl-aħħar iġibhom fl-ilma nadif. Ejja nittrattaw ukoll dawn it-tipi suspettużi.

It-tajpjar tad-dejta f'PostgreSQL, għal kull loġika tiegħu, xi drabi jippreżenta sorpriżi strambi ħafna. F'dan l-artikolu ser nippruvaw niċċaraw xi wħud mill-kwirkijiet tagħhom, nifhmu r-raġuni għall-imġieba stramba tagħhom u nifhmu kif ma tiddependix fi problemi fil-prattika ta 'kuljum. Biex ngħid il-verità, ikkumpilajt dan l-artiklu wkoll bħala speċi ta’ ktieb ta’ referenza għalija nnifsi, ktieb ta’ referenza li jista’ jsir referenza għalih faċilment f’każijiet kontroversjali. Għalhekk, se jiġi rifornit hekk kif jiġu skoperti sorpriżi ġodda minn tipi suspettużi. Allura, ejja, oh trackers tad-database bla heda!

Dossier numru wieħed. reali/preċiżjoni doppja/numeriċi/flus

Jidher li t-tipi numeriċi huma l-inqas problematiċi f'termini ta 'sorpriżi fl-imġieba. Imma ma jimpurtax kif ikun. Mela ejja nibdew magħhom. Allura…

Insejt kif tgħodd

SELECT 0.1::real = 0.1

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

X'ġara? Il-problema hija li PostgreSQL jikkonverti l-kostanti mhux ittajpjat 0.1 għal preċiżjoni doppja u jipprova jqabbelha ma '0.1 tat-tip reali. U dawn huma tifsiriet kompletament differenti! L-idea hija li tirrappreżenta numri reali fil-memorja tal-magni. Peress li 0.1 ma jistax jiġi rappreżentat bħala frazzjoni binarja finita (tkun 0.0 (0011) f'binarju), numri b'fond ta 'bit differenti se jkunu differenti, għalhekk ir-riżultat li mhumiex ugwali. B'mod ġenerali, dan huwa suġġett għal artiklu separat mhux se nikteb f'aktar dettall hawn.

Minn fejn ġej l-iżball?

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

Ħafna nies jafu li PostgreSQL jippermetti notazzjoni funzjonali għall-ikkastjar tat-tip. Jiġifieri, tista 'tikteb mhux biss 1::int, iżda wkoll int(1), li se tkun ekwivalenti. Iżda mhux għal tipi li l-ismijiet tagħhom jikkonsistu f'diversi kliem! Għalhekk, jekk trid titfa 'valur numeriku għal tip ta' preċiżjoni doppja f'forma funzjonali, uża l-psewdonomi ta 'dan it-tip float8, jiġifieri SELECT float8(1).

X'hemm akbar mill-infinit?

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

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

Ħares kif inhu! Jirriżulta li hemm xi ħaġa akbar minn infinità, u huwa NaN! Fl-istess ħin, id-dokumentazzjoni PostgreSQL tħares lejna b'għajnejn onesti u ssostni li NaN huwa ovvjament akbar minn kwalunkwe numru ieħor, u, għalhekk, infinità. L-oppost huwa veru wkoll għal -NaN. Hello, min iħobb il-matematika! Imma rridu niftakru li dan kollu jopera fil-kuntest tan-numri reali.

Arrotondament tal-għajnejn

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

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

Tislima oħra mhux mistennija mill-bażi. Għal darb'oħra, ftakar li l-preċiżjoni doppja u t-tipi numeriċi għandhom effetti ta' arrotondament differenti. Għal numeriku - il-mod tas-soltu, meta 0,5 huwa mqarreb 'l fuq, u għal preċiżjoni doppja - 0,5 huwa mqarreb lejn l-eqreb numru sħiħ ugwali.

Il-flus huma xi ħaġa speċjali

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

Skont PostgreSQL, il-flus mhumiex numru reali. Skond xi individwi, ukoll. Irridu niftakru li l-ikkastjar tat-tip ta 'flus huwa possibbli biss għat-tip numeriku, hekk kif it-tip numeriku biss jista' jiġi mitfugħ għat-tip ta 'flus. Imma issa tista’ tilgħab magħha kif tixtieq qalbek. Imma mhux se jkunu l-istess flus.

Ġenerazzjoni żgħira u sekwenza

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 ma jħobbx jaħli ħin fuq trifles. X'inhuma dawn is-sekwenzi bbażati fuq smallint? int, mhux inqas! Għalhekk, meta tipprova tesegwixxi l-mistoqsija ta 'hawn fuq, id-database tipprova titfa' smallint għal xi tip ta' numru sħiħ ieħor, u tara li jista 'jkun hemm diversi casts bħal dawn. Liema mitfugħa tagħżel? Hija ma tistax tiddeċiedi dan, u għalhekk tiġġarraf bi żball.

Fajl numru tnejn. "char"/char/varchar/test

Numru ta 'oddities huma wkoll preżenti fit-tipi ta' karattri. Ejja nsiru nafuhom ukoll.

X'tip ta' tricks huma dawn?

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

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

X'tip ta' "char" huwa dan, x'tip ta' clown huwa dan? M'għandniex bżonn dawk... Għax tippretendi li hija char ordinarja, minkejja li tkun bil-kwotazzjonijiet. U huwa differenti minn char regolari, li huwa mingħajr kwotazzjonijiet, peress li joħroġ biss l-ewwel byte tar-rappreżentazzjoni ta 'sekwenza, filwaqt li char normali joħroġ l-ewwel karattru. Fil-każ tagħna, l-ewwel karattru huwa l-ittra P, li fir-rappreżentazzjoni tal-unicode tieħu 2 bytes, kif jidher billi tikkonverti r-riżultat għat-tip bytea. U t-tip "char" jieħu biss l-ewwel byte ta 'din ir-rappreżentazzjoni unicode. Allura għaliex dan it-tip huwa meħtieġ? Id-dokumentazzjoni PostgreSQL tgħid li dan huwa tip speċjali użat għal bżonnijiet speċjali. Għalhekk mhux probabbli li jkollna bżonnha. Imma ħares f’għajnejh u ma tiżbaljax meta tiltaqa’ miegħu bl-imġieba speċjali tiegħu.

Spazji żejda. Mill-vista, barra mill-moħħ

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

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

Agħti ħarsa lejn l-eżempju mogħti. I kkonvertit b'mod speċjali r-riżultati kollha għat-tip bytea, sabiex ikun jidher b'mod ċar dak li kien hemm. Fejn huma l-ispazji ta 'wara wara l-ikkastjar għal varchar (6)? Id-dokumentazzjoni tgħid fil-qosor: "Meta titfa' l-valur ta' karattru għal tip ta' karattru ieħor, l-ispazju abjad ta' wara jintrema." Din id-dislike trid tiġi mfakkar. U innota li jekk kostanti ta 'sekwenza kkwotata tiġi mitfugħa direttament għat-tip varchar(6), l-ispazji ta' wara jiġu ppreservati. Dawn huma l-mirakli.

Fajl numru tlieta. json/jsonb

JSON hija struttura separata li tgħix il-ħajja tagħha stess. Għalhekk, l-entitajiet tagħha u dawk ta 'PostgreSQL huma kemmxejn differenti. Hawn huma eżempji.

Johnson u Johnson. tħoss id-differenza

SELECT 'null'::jsonb IS NULL

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

Il-ħaġa hija li JSON għandu l-entità nulla tiegħu stess, li mhix l-analogu ta 'NULL f'PostgreSQL. Fl-istess ħin, l-oġġett JSON innifsu jista 'jkollu l-valur NULL, għalhekk l-espressjoni SELECT null::jsonb IS NULL (innota n-nuqqas ta' kwotazzjonijiet singoli) se terġa 'lura vera din id-darba.

Ittra waħda tbiddel kollox

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]}

Il-ħaġa hija li json u jsonb huma strutturi kompletament differenti. F'json, l-oġġett jinħażen kif inhu, u f'jsonb huwa diġà maħżun fil-forma ta' struttura parsed u indiċjata. Huwa għalhekk li fit-tieni każ, il-valur tal-oġġett b'ċavetta 1 ġie sostitwit minn [1, 2, 3] għal [7, 8, 9], li daħal fl-istruttura fl-aħħar nett bl-istess ċavetta.

Tixrobx ilma minn wiċċek

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

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

PostgreSQL fl-implimentazzjoni JSONB tiegħu jibdel l-ifformattjar ta 'numri reali, u jġibhom għall-forma klassika. Dan ma jiġrix għat-tip JSON. Xi ftit stramba, imma għandu raġun.

Fajl numru erbgħa. data/ħin/timestamp

Hemm ukoll xi oddities b'tipi ta 'data/ħin. Ejja nħarsu lejhom. Ħa nagħmel riżerva minnufih li xi wħud mill-karatteristiċi tal-imġieba jsiru ċari jekk tifhem sew l-essenza tal-ħidma maż-żoni tal-ħin. Iżda dan huwa wkoll suġġett għal artiklu separat.

Tiegħi ma tifhimx

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

Jidher li dak li huwa inkomprensibbli hawn? Imma d-database għadha ma tifhimx dak li poġġejna fl-ewwel post hawn—is-sena jew il-ġurnata? U tiddeċiedi li hija d-99 ta’ Jannar, 2008, li jonfaħha moħħha. B'mod ġenerali, meta tittrażmetti d-dati f'format ta 'test, għandek bżonn tiċċekkja b'attenzjoni kbira kemm id-database għarfethom b'mod korrett (b'mod partikolari, tanalizza l-parametru tad-datestyle bil-kmand SHOW datestyle), peress li l-ambigwitajiet f'din il-kwistjoni jistgħu jkunu għaljin ħafna.

Minn fejn ħadt dan?

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

Għaliex id-database ma tistax tifhem il-ħin speċifikat b'mod espliċitu? Minħabba li ż-żona tal-ħin m'għandhiex abbrevjazzjoni, iżda isem sħiħ, li jagħmel sens biss fil-kuntest ta 'data, peress li tqis l-istorja tal-bidliet fiż-żona tal-ħin, u ma taħdimx mingħajr data. U l-kliem stess tal-linja tal-ħin iqajjem mistoqsijiet - x'ried verament ifisser il-programmatur? Għalhekk, kollox huwa loġiku hawn, jekk tħares lejha.

X'hemm ħażin miegħu?

Immaġina s-sitwazzjoni. Għandek qasam fit-tabella tiegħek bit-tip timestamptz. Trid indiċiha. Imma tifhem li l-bini ta 'indiċi fuq dan il-qasam mhux dejjem ikun iġġustifikat minħabba s-selettività għolja tiegħu (kważi l-valuri kollha ta' dan it-tip se jkunu uniċi). Allura inti tiddeċiedi li tnaqqas is-selettività ta 'l-indiċi billi titfa' t-tip għal data. U ikollok sorpriża:

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

X'ġara? Il-fatt hu li biex titfa 'tip timestamptz għal tip ta' data, jintuża l-valur tal-parametru tas-sistema TimeZone, li jagħmel il-funzjoni ta 'konverżjoni tat-tip dipendenti fuq parametru tad-dwana, i.e. volatili. Funzjonijiet bħal dawn mhumiex permessi fl-indiċi. F'dan il-każ, trid tindika b'mod espliċitu f'liema żona tal-ħin titwettaq it-tip cast.

Meta issa lanqas issa xejn

Aħna mdorrijin biex issa () nirritornaw id-data/ħin attwali, b'kont meħud taż-żona tal-ħin. Imma ħares lejn il-mistoqsijiet li ġejjin:

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;

Id-data/ħin jintbagħtu lura l-istess irrispettivament minn kemm għadda żmien mit-talba preċedenti! X'ġara? Il-fatt hu li issa () mhuwiex il-ħin kurrenti, iżda l-ħin tal-bidu tat-tranżazzjoni kurrenti. Għalhekk, ma tinbidilx fi ħdan it-tranżazzjoni. Kwalunkwe mistoqsija mnedija barra l-ambitu ta 'tranżazzjoni hija mgeżwra fi transazzjoni impliċitament, u huwa għalhekk li ma ninnutawx li l-ħin ritornat minn sempliċi SELECT issa (); fil-fatt, mhux dak kurrenti... Jekk trid tikseb ħin attwali onest, trid tuża l-funzjoni clock_timestamp().

Fajl numru ħamsa. daqsxejn

Stramba ftit

SELECT '111'::bit(4)

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

Liema naħa għandhom jiġu miżjuda l-bits fil-każ ta 'estensjoni tat-tip? Jidher li huwa fuq ix-xellug. Iżda l-bażi biss għandha opinjoni differenti dwar din il-kwistjoni. Oqgħod attent: jekk in-numru ta 'ċifri ma jaqbilx meta titfa' tip, ma jkollokx dak li ridt. Dan japplika kemm għaż-żieda tal-bits fuq il-lemin kif ukoll għat-tirqim tal-bits. Fuq il-lemin ukoll...

File numru sitta. Arrays

Anke NULL ma sparax

SELECT ARRAY[1, 2] || NULL

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

Bħala nies normali mqajma fuq SQL, nistennew li r-riżultat ta 'din l-espressjoni jkun NULL. Imma ma kienx hemm. Jiġi rritornat firxa. Għaliex? Minħabba li f'dan il-każ il-bażi titfa 'NULL għal firxa ta' numru sħiħ u impliċitament issejjaħ il-funzjoni array_cat. Iżda għadu mhux ċar għaliex dan il-"qattus tal-array" ma jerġax isettja l-firxa. Din l-imġieba wkoll trid tiġi mfakkar.

Agħti fil-qosor. Hemm ħafna affarijiet strambi. Ħafna minnhom, ovvjament, mhumiex daqshekk kritiċi li jitkellmu dwar imġieba sfaċċatament mhux xierqa. U oħrajn huma spjegati bil-faċilità ta 'użu jew il-frekwenza tal-applikabilità tagħhom f'ċerti sitwazzjonijiet. Iżda fl-istess ħin, hemm ħafna sorpriżi. Għalhekk, trid tkun taf dwarhom. Jekk issib xi ħaġa oħra stramba jew mhux tas-soltu fl-imġieba ta 'kwalunkwe tip, ikteb fil-kummenti, inkun kuntent li nżid mad-dossiers disponibbli fuqhom.

Sors: www.habr.com

Żid kumment