Seòrsan amharasach

Chan eil dad amharasach mun choltas aca. A bharrachd air an sin, tha iad eadhon eòlach ort gu math agus airson ùine mhòr. Ach chan eil sin ach gus an dèan thu sgrùdadh orra. Seo far am bi iad a’ sealltainn an nàdar brùideil, ag obair gu tur eadar-dhealaichte na bha dùil agad. Agus uaireannan bidh iad a 'dèanamh rudeigin a bheir air do fhalt seasamh aig an deireadh - mar eisimpleir, bidh iad a' call an dàta dìomhair a chaidh a thoirt dhaibh. Nuair a chuireas tu an aghaidh iad, bidh iad ag agairt nach eil iad eòlach air a chèile, ged a tha iad ag obair gu cruaidh fon aon chochall anns na faileasan. Tha an t-àm ann an toirt gu uisge glan mu dheireadh. Leig leinn cuideachd dèiligeadh ris na seòrsaichean amharasach sin.

Bidh taidhpeadh dàta ann am PostgreSQL, airson a h-uile loidsig, uaireannan a’ nochdadh iongnadh neònach. Anns an aiste seo bidh sinn a 'feuchainn ri soilleireachadh cuid de na quirks aca, a' tuigsinn an t-adhbhar airson an giùlan neònach agus a 'tuigsinn mar nach eil a' ruith a-steach do dhuilgheadasan ann an cleachdadh làitheil. Leis an fhìrinn innse, chuir mi ri chèile an artaigil seo cuideachd mar sheòrsa de leabhar fiosrachaidh dhomh fhìn, leabhar fiosrachaidh a dh’ fhaodadh a bhith furasta iomradh a thoirt air ann an cùisean connspaideach. Mar sin, bidh e air ath-lìonadh mar a lorgar iongnadh ùra bho sheòrsan amharasach. Mar sin, rachamaid, o luchd-leantainn stòr-dàta gun sgur!

Dossier àireamh a h-aon. fìor/dùbailte mionaideachd/àireamhach/airgead

Bhiodh e coltach gur e seòrsaichean àireamhach an fheadhainn as lugha de dhuilgheadas a thaobh iongnadh ann an giùlan. Ach ge bith ciamar a tha e. Mar sin tòisichidh sinn leotha. Mar sin…

Na dhìochuimhnich thu mar a nì thu cunntadh

SELECT 0.1::real = 0.1

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

Dè tha ceàrr? Is e an duilgheadas a th ’ann gu bheil PostgreSQL ag atharrachadh an seasmhach neo-chlàraichte 0.1 gu mionaideachd dùbailte agus a’ feuchainn ri coimeas a dhèanamh eadar e agus 0.1 de fhìor sheòrsa. Agus tha iad sin nan ciall gu tur eadar-dhealaichte! Is e am beachd àireamhan fìor a riochdachadh ann an cuimhne inneal. Leis nach urrainn 0.1 a bhith air a riochdachadh mar bloigh binary crìochnaichte (bhiodh e 0.0(0011) ann am binary), bidh àireamhan le doimhneachd eadar-dhealaichte eadar-dhealaichte, agus mar sin an toradh nach eil iad co-ionann. San fharsaingeachd, is e cuspair a tha seo airson artaigil air leth; cha sgrìobh mi nas mionaidiche an seo.

Cò às a tha am mearachd a’ tighinn?

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

Tha fios aig mòran dhaoine gu bheil PostgreSQL a’ ceadachadh comharradh gnìomh airson tilgeadh seòrsa. Is e sin, faodaidh tu sgrìobhadh chan ann a-mhàin 1::int, ach cuideachd int(1), a bhios co-ionann. Ach chan ann airson seòrsaichean aig a bheil ainmean grunn fhaclan! Mar sin, ma tha thu airson luach àireamhach a thilgeil gu seòrsa mionaideachd dùbailte ann an cruth gnìomh, cleachd an alias den t-seòrsa float8, is e sin, SELECT float8(1).

Dè a tha nas motha na Infinity?

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

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

Seall cò ris a tha e coltach! Tha e a ’tionndadh a-mach gu bheil rudeigin nas motha na Infinity, agus is e NaN a th’ ann! Aig an aon àm, tha sgrìobhainnean PostgreSQL a’ coimhead oirnn le sùilean onarach agus ag agairt gu bheil NaN gu follaiseach nas motha na àireamh sam bith eile, agus, mar sin, Infinity. Tha an taobh eile fìor cuideachd airson -NaN. Halo, leannanan matamataigs! Ach feumaidh sinn cuimhneachadh gu bheil seo uile ag obrachadh ann an co-theacsa àireamhan fìor.

A 'cuairteachadh nan sùilean

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

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

Beannachd eile ris nach robh dùil bhon bhonn. A-rithist, cuimhnich gu bheil buaidhean cruinneachaidh eadar-dhealaichte aig cruinneas dùbailte agus seòrsachan àireamhach. Airson àireamhach - an tè àbhaisteach, nuair a tha 0,5 cruinn, agus airson mionaideachd dùbailte - tha 0,5 air a chuairteachadh chun an t-slànaighear eadhon as fhaisge.

Tha airgead rudeigin sònraichte

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

A rèir PostgreSQL, chan e fìor àireamh a th’ ann an airgead. A rèir cuid de dhaoine, cuideachd. Feumaidh sinn cuimhneachadh nach eil e comasach an seòrsa airgid a thilgeil a-mhàin don t-seòrsa àireamhach, dìreach mar nach urrainnear ach an seòrsa àireamhach a thilgeil don t-seòrsa airgid. Ach a-nis faodaidh tu cluich leis mar a tha do chridhe ag iarraidh. Ach chan e an aon airgead a bhios ann.

Smallint agus ginealach sreath

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

Cha toil le PostgreSQL ùine a chaitheamh air trifles. Dè a tha na sreathan sin stèidhichte air smallint? int, chan eil nas lugha! Mar sin, nuair a thathar a’ feuchainn ris a’ cheist gu h-àrd a chuir an gnìomh, bidh an stòr-dàta a’ feuchainn ri smallint a thilgeil gu seòrsa sloinntearachd air choireigin eile, agus a’ faicinn gur dòcha gu bheil grunn chasan mar sin ann. Dè an rionnag a thaghadh? Chan urrainn dhi seo a cho-dhùnadh, agus mar sin bidh i a’ tuiteam le mearachd.

Faidhle àireamh a dhà. "char"/char/varchar/text

Tha grunn rudan neònach cuideachd an làthair ann an seòrsachan caractar. Leig leinn eòlas fhaighinn orra cuideachd.

Dè an seòrsa cleas a tha seo?

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

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

Dè an seòrsa "char" a tha seo, dè an seòrsa clown a tha seo? Chan eil feum againn air an fheadhainn sin... Leis gu bheil e a’ leigeil a-mach gur e char àbhaisteach a th’ ann, ged a tha e ann an luachan. Agus tha e eadar-dhealaichte bho char àbhaisteach, a tha gun luachan, leis nach eil e a’ toirt a-mach ach a’ chiad byte de riochdachadh sreang, fhad ‘s a tha char àbhaisteach a’ toirt a-mach a ’chiad charactar. Anns a 'chùis againn, is e a' chiad charactar an litir P, a tha anns an riochdachadh Unicode a 'toirt suas 2 bytes, mar a chithear le bhith ag atharrachadh an toradh gu seòrsa bytea. Agus chan eil an seòrsa “char” a’ gabhail ach a’ chiad byte den riochdachadh unicode seo. An uairsin carson a tha feum air an seòrsa seo? Tha sgrìobhainnean PostgreSQL ag ràdh gur e seòrsa sònraichte a tha seo airson feumalachdan sònraichte. Mar sin chan eil e coltach gum bi feum againn air. Ach seall a-steach dha shùilean agus cha bhith thu ceàrr nuair a choinnicheas tu ris leis a ghiùlan sònraichte.

Àiteachan a bharrachd. As an t-sealladh, as an inntinn

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

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

Thoir sùil air an eisimpleir a chaidh a thoirt seachad. Thionndaidh mi na toraidhean gu lèir gu seòrsa bytea gu sònraichte, gus am biodh e follaiseach gu soilleir na bha ann. Càite a bheil na h-àiteachan tarraing às deidh an tilgeadh gu varchar (6)? Tha na sgrìobhainnean gu h-aithghearr ag ràdh: “Nuair a thathar a’ tilgeil luach caractar gu seòrsa caractar eile, thèid àite geal a thilgeil air falbh." Feumar cuimhneachadh air a’ mhì-thoileachas seo. Agus thoir an aire ma thèid sreang sreang ainmichte a thilgeil gu dìreach gu seòrsa varchar (6), tha na h-àiteachan slaodadh air an gleidheadh. Is iad sin na mìorbhuilean.

Faidhle àireamh a trì. json/son

Tha JSON na structar air leth a tha a’ fuireach a bheatha fhèin. Mar sin, tha na h-aonadan aige agus feadhainn PostgreSQL beagan eadar-dhealaichte. Seo eisimpleirean.

Johnson agus Johnson. faireachdainn an diofar

SELECT 'null'::jsonb IS NULL

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

Is e an rud gu bheil an eintiteas null aige fhèin aig JSON, nach e an analogue de NULL ann am PostgreSQL. Aig an aon àm, is dòcha gu bheil luach NULL aig an nì JSON fhèin, agus mar sin tillidh an abairt SELECT null ::jsonb IS NULL (thoir an aire nach eil luachan singilte ann) fìor an turas seo.

Bidh aon litir ag atharrachadh a h-uile càil

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

Is e an rud gu bheil json agus jsonb nan structaran gu tur eadar-dhealaichte. Ann an json, tha an nì air a stòradh mar a tha, agus ann an jsonb tha e mu thràth air a stòradh ann an cruth structar parsed, clàr-amais. Sin as coireach anns an dàrna cùis, chaidh luach an nì le iuchair 1 a chuir na àite bho [1, 2, 3] gu [7, 8, 9], a thàinig a-steach don structar aig an deireadh leis an aon iuchair.

Na bi ag òl uisge bho d’aghaidh

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

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

Bidh PostgreSQL na bhuileachadh JSONB ag atharrachadh cruth àireamhan fìor, gan toirt chun chruth clasaigeach. Chan eil seo a' tachairt airson an t-seòrsa JSON. Beagan neònach, ach tha e ceart.

Faidhle àireamh a ceithir. ceann-latha/ùine/stampa

Tha cuid de rudan neònach ann cuideachd le seòrsaichean ceann-latha/ùine. Bheir sinn sùil orra. Leig leam glèidheadh ​​​​sa bhad gum bi cuid de na feartan giùlain soilleir ma tha thu a’ tuigsinn gu math brìgh a bhith ag obair le sònaichean ùine. Ach tha seo cuideachd na chuspair airson artaigil air leth.

Chan eil mo chuid-sa a’ tuigsinn

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

Bhiodh e coltach gu bheil dè a tha do-thuigsinn an seo? Ach chan eil an stòr-dàta fhathast a’ tuigsinn dè a chuir sinn an sàs an seo - a’ bhliadhna neo an latha? Agus tha i a’ co-dhùnadh gur e 99 Faoilleach 2008 a tha a’ sèideadh a h-inntinn. San fharsaingeachd, nuair a bhios tu a’ tar-chuir cinn-latha ann an cruth teacsa, feumaidh tu dèanamh cinnteach gu faiceallach dè cho ceart ‘s a dh’ aithnich an stòr-dàta iad (gu sònraichte, dèan mion-sgrùdadh air paramadair stoidhle ceann-latha leis an àithne SHOW datestyle command), oir faodaidh teagmhachdan sa chùis seo a bhith gu math daor.

Cò às a fhuair thu seo?

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

Carson nach tuig an stòr-dàta an ùine a chaidh a shònrachadh gu soilleir? Leis nach eil giorrachadh aig an raon ùine, ach ainm slàn, a tha a ’dèanamh ciall a-mhàin ann an co-theacsa ceann-latha, leis gu bheil e a’ toirt aire do eachdraidh atharrachaidhean sòn ùine, agus chan eil e ag obair gun cheann-latha. Agus tha fìor bhriathrachas na loidhne-tìm a’ togail cheistean - dè bha am prògramadair a’ ciallachadh dha-rìribh? Mar sin, tha a h-uile dad loidsigeach an seo, ma choimheadas tu air.

Dè tha ceàrr air?

Smaoinich air an t-suidheachadh. Tha raon agad air a’ bhòrd agad le seòrsa timestamptz. Tha thu airson a chlàr-amais. Ach tuigidh tu nach eil togail clàr-amais san raon seo an-còmhnaidh air fhìreanachadh air sgàth cho àrd ‘s a tha e (bidh cha mhòr a h-uile luach den t-seòrsa seo gun samhail). Mar sin bidh thu a’ co-dhùnadh taghadh a’ chlàr-amais a lughdachadh le bhith a’ cur an seòrsa gu ceann-latha. Agus gheibh thu iongnadh:

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

Dè tha ceàrr? Is e an fhìrinn, gus seòrsa stampa-ama a thilgeil gu seòrsa ceann-latha, gu bheil luach paramadair siostam TimeZone air a chleachdadh, a tha a’ dèanamh a ’ghnìomh tionndaidh seòrsa an urra ri paramadair àbhaisteach, i.e. luaineach. Chan eil gnìomhan leithid seo ceadaichte sa chlàr-amais. Anns a 'chùis seo, feumaidh tu innse gu soilleir dè an raon ùine a tha an seòrsa tilgeadh air a dhèanamh.

Nuair nach eil a-nis eadhon a-nis idir

Tha sinn cleachdte ri a-nis () an ceann-latha / àm làithreach a thilleadh, a’ toirt aire don raon ùine. Ach thoir sùil air na ceistean a leanas:

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;

Tha an ceann-latha/ùine air a thilleadh mar an ceudna ge bith dè an ùine a chaidh seachad bhon iarrtas roimhe! Dè tha ceàrr? Is e an fhìrinn nach e a-nis () an ùine làithreach, ach àm tòiseachaidh a’ ghnothaich gnàthach. Mar sin, chan eil e ag atharrachadh taobh a-staigh a 'ghnothaich. Tha ceist sam bith a thèid a chuir air bhog taobh a-muigh raon malairt air a phasgadh ann an malairt gu h-obann, agus is e sin as coireach nach eil sinn a’ mothachadh gu bheil an ùine air a thilleadh le SELECT sìmplidh a-nis(); gu dearbh, chan e am fear a th' ann an-dràsta... Ma tha thu airson ùine làithreach onarach fhaighinn, feumaidh tu an gnìomh clock_timestamp () a chleachdadh.

Faidhle àireamh a còig. beagan

Beagan neònach

SELECT '111'::bit(4)

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

Dè an taobh a bu chòir na pìosan a chur ris ma thèid an seòrsa leudachadh? Tha e coltach gu bheil e air an taobh chlì. Ach chan eil ach beachd eadar-dhealaichte aig a 'bhunait air a' chùis seo. Bi faiceallach: mura h-eil an àireamh de dh’ àireamhan a’ freagairt nuair a bhios tu a’ tilgeil seòrsa, chan fhaigh thu na bha thu ag iarraidh. Tha seo a 'buntainn ris an dà chuid a bhith a' cur phìosan ris an làimh dheis agus a 'gearradh pìosan. Cuideachd air an làimh dheis ...

Faidhle àireamh a sia. Arrays

Cha do loisg eadhon NULL

SELECT ARRAY[1, 2] || NULL

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

Mar a thog daoine àbhaisteach air SQL, tha sinn an dùil gur e toradh an abairt seo NULL. Ach cha robh e ann. Tha sreath air a thilleadh. Carson? Leis anns a’ chùis seo bidh am bonn a’ tilgeadh NULL gu sreath sèimh agus gu h-obann a’ gairm gnìomh array_cat. Ach chan eil e soilleir fhathast carson nach eil an “cat eagrachaidh” seo ag ath-shuidheachadh an t-sreath. Feumaidh an giùlan seo dìreach cuimhneachadh cuideachd.

Geàrr-chunntas. Tha gu leòr de rudan annasach. Tha a’ mhòr-chuid dhiubh, gu dearbh, nach eil cho èiginneach ri bhith a’ bruidhinn mu dheidhinn giùlan mì-fhreagarrach. Agus tha cuid eile air am mìneachadh le furasta an cleachdadh no cho tric sa tha iad iomchaidh ann an suidheachaidhean sònraichte. Ach aig an aon àm, tha mòran iongnadh ann. Mar sin, feumaidh fios a bhith agad mun deidhinn. Ma lorgas tu rud sam bith eile neònach no neo-àbhaisteach ann an giùlan de sheòrsa sam bith, sgrìobh anns na beachdan, bidh mi toilichte cuir ris na clàran a tha rim faighinn orra.

Source: www.habr.com

Cuir beachd ann