-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtypes.xml
2586 lines (2494 loc) · 169 KB
/
types.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE chapter>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="types" xml:lang="ru">
<info>
<title>Типы данных</title>
</info>
<para>Типы данных используются в случае: <itemizedlist>
<listitem>
<para>определения столбца в таблице базы данных в операторе CREATE TABLE или для его
изменения с использованием ALTER TABLE;</para>
</listitem>
<listitem>
<para>при объявлении и редактировании домена оператором CREATE DOMAIN/ALTER DOMAIN;
</para>
</listitem>
<listitem>
<para>при объявлении локальных переменных в хранимых процедурах, функциях,
PSQL-блоках и триггерах, при указании аргументов хранимых процедур и функций;
</para>
</listitem>
<listitem>
<para>при описании внешних функций (UDF – функций, определённых пользователем) для
указания аргументов и возвращаемых значений; </para>
</listitem>
<listitem>
<para>при явном преобразовании типов данных в качестве аргумента для функции CAST.
</para>
</listitem>
</itemizedlist>
</para>
<para>
<table>
<?dbfo keep-together='auto'?>
<title>Типы данных Firebird</title>
<tgroup cols="4">
<colspec colname="colName" colwidth="1*" align="left"/>
<colspec colname="colSize" colwidth="1*" align="left"/>
<colspec colname="colPrecision" colwidth="1*" align="left"/>
<colspec colname="colDesc" colwidth="2*" align="left"/>
<thead>
<row valign="middle">
<entry align="center">Название</entry>
<entry align="center">Размер</entry>
<entry align="center">Диапазон и точность</entry>
<entry align="center">Описание</entry>
</row>
</thead>
<tbody>
<row>
<entry>BIGINT</entry>
<entry>64 бита</entry>
<entry>-2<superscript>63</superscript> .. 2<superscript>63</superscript> -
1</entry>
<entry>Тип данных доступен только в 3 диалекте.</entry>
</row>
<row>
<entry>BLOB</entry>
<entry>Переменный</entry>
<entry>Нет. Размер сегмента BLOB ограничивается 64К. Максимальный размер
поля BLOB 4 Гб. Для размера страницы 4096 максимальный размер BLOB поля
несколько ниже 2 Гб.</entry>
<entry>Тип данных с динамически изменяемым размером для хранения больших
данных, таких как графика, тексты, оцифрованные звуки. Базовая
структурная единица — сегмент. Подтип Blob описывает содержимое.
</entry>
</row>
<row>
<entry>BOOLEAN</entry>
<entry>8 бит</entry>
<entry>false, true, unknown</entry>
<entry>Логический тип данных.</entry>
</row>
<row>
<entry>
<para>CHAR(<replaceable>n</replaceable>)</para>
<para>CHARACTER(<replaceable>n</replaceable>)</para>
</entry>
<entry><replaceable>n</replaceable> символов (размер в байтах зависит от
кодировки, кол-во байт на символ)</entry>
<entry>от 1 до 32 767 байт</entry>
<entry>Символьный тип данных фиксированной длины. При извлечении данных,
строка дополняется пробелами справа до указанной длины. Если количество
символов <replaceable>n</replaceable> не указано, то по умолчанию
принимается 1.</entry>
</row>
<row>
<entry>DATE</entry>
<entry>32 бита</entry>
<entry>От 01.01.0001 н.э. до 31.12.9999 н.э.</entry>
<entry>ISC_DATE</entry>
</row>
<row>
<entry>DECIMAL (<replaceable>precision</replaceable>,
<replaceable>scale</replaceable>)</entry>
<entry>Переменный (16, 32 или 64 бита)</entry>
<entry>
<para><replaceable>precision</replaceable> = от 1 до 18, указывает, по
меньшей мере, количество цифр для хранения;</para>
<para><replaceable>scale</replaceable> = от 0 до 18. Задаёт количество
знаков после разделителя </para>
</entry>
<entry><replaceable>scale</replaceable> должно быть меньше или равно
<replaceable>precision</replaceable>. Число с десятичной точкой,
имеющей после точки <replaceable>scale</replaceable> разрядов. Пример:
DECIMAL(10,3) содержит число точно в следующем формате: ppppppp.sss.
</entry>
</row>
<row>
<entry>DOUBLE PRECISION</entry>
<entry>64 бита</entry>
<entry>2,225 x 10<superscript>-308</superscript> .. 1,797 x
10<superscript>308</superscript>
</entry>
<entry>IEEE двойной точности, 15 цифр, размер зависит от платформы </entry>
</row>
<row>
<entry>FLOAT</entry>
<entry>32 бита</entry>
<entry>1,175 x 10<superscript>-38</superscript> .. 3,402 x
10<superscript>38</superscript>
</entry>
<entry>IEEE одинарной точности, 7 цифр </entry>
</row>
<row>
<entry>
<para>INTEGER</para>
<para>INT</para>
</entry>
<entry>32 бита</entry>
<entry>–2 147 483 648 .. 2 147 483 647</entry>
<entry>signed long</entry>
</row>
<row>
<entry>NUMERIC (<replaceable>precision</replaceable>,
<replaceable>scale</replaceable>)</entry>
<entry>Переменный (16, 32 или 64 бита)</entry>
<entry>
<para><replaceable>precision</replaceable> = от 1 до 18, указывает, по
меньшей мере, количество цифр для хранения;</para>
<para><replaceable>scale</replaceable> = от 0 до 18. Задаёт количество
знаков после разделителя.</para>
</entry>
<entry><replaceable>scale</replaceable> должно быть меньше или равно
precision. Число с десятичной точкой, имеющей после точки scale
разрядов. Пример: NUMERIC(10,3) содержит число точно в следующем
формате: ppppppp.sss.</entry>
</row>
<row>
<entry>REAL</entry>
<entry>32 бита</entry>
<entry>1,175 x 10<superscript>-38</superscript> .. 3,402 x
10<superscript>38</superscript>
</entry>
<entry>Является синонимом типа FLOAT.</entry>
</row>
<row>
<entry>SMALLINT</entry>
<entry>16 бит</entry>
<entry>–32 768 .. 32 767</entry>
<entry>signed short (word)</entry>
</row>
<row>
<entry>TIME</entry>
<entry>32 бита</entry>
<entry>От 0:00 до 23:59:59.9999</entry>
<entry>ISC_TIME </entry>
</row>
<row>
<entry>TIMESTAMP</entry>
<entry>64 бита</entry>
<entry>От 01.01.0001 н.э. до 31.12.9999 н.э.</entry>
<entry>Включает информацию и о времени</entry>
</row>
<row>
<entry>
<para>VARCHAR(<replaceable>n</replaceable>)</para>
<para>CHAR VARYING</para>
<para>CHARACTER VARYING</para>
</entry>
<entry><replaceable>n</replaceable> символов (размер в байтах зависит от
кодировки, кол-ва байт на символ) </entry>
<entry>От 1 до 32 765 байтов</entry>
<entry>Размер символов в байтах с учётом их кодировки не может быть больше
32765. Для этого типа данных, в отличие от CHAR (где по умолчанию
предполагается количество символов 1), количество символов n обязательно
должно быть указано.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<note>
<para>Следует иметь в виду, что временной ряд из дат прошлых веков рассматривается без учёта
реальных исторических фактов и так, как будто бы во всем этом диапазоне ВСЕГДА
действовал только Григорианский календарь. </para>
</note>
<section xml:id="types-integer">
<info>
<title>Целочисленные типы данных</title>
</info>
<para>Для целых чисел используют целочисленные типы данных SMALLINT, INTEGER и BIGINT (в 3
диалекте). Firebird не поддерживает беззнаковый целочисленный тип данных. </para>
<section xml:id="types-integer-smallint">
<info>
<title>SMALLINT</title>
</info>
<indexterm><primary>SMALLINT</primary></indexterm>
<para>Тип данных SMALLINT представляет собой 16-битное целое. Он применяется в случае,
когда не требуется широкий диапазон возможных значений для хранения данных. </para>
<para>Числа типа SMALLINT находятся в диапазоне -2<superscript>15</superscript> ..
2<superscript>15</superscript> - 1, или -32 768 .. 32 767. </para>
<formalpara>
<title>Примеры:</title>
<para>
<programlisting language="sql">
CREATE DOMAIN DFLAG AS SMALLINT DEFAULT 0 NOT NULL
CHECK (VALUE=-1 OR VALUE=0 OR VALUE=1);
CREATE DOMAIN RGB_VALUE AS SMALLINT;
</programlisting>
</para>
</formalpara>
</section>
<section xml:id="types-integer-int">
<info>
<title>INTEGER</title>
</info>
<indexterm><primary>INTEGER</primary></indexterm>
<para>Тип данных INTEGER представляет собой 32-битное целое. Сокращённый вариант записи
типа данных INT.</para>
<para>Числа типа INTEGER находятся в диапазоне -2<superscript>31</superscript> ..
2<superscript>31</superscript> - 1, или -2 147 483 648 .. 2 147 483 647.</para>
<formalpara>
<title>Примеры:</title>
<para>
<programlisting language="sql">
CREATE TABLE CUSTOMER (
CUST_NO INTEGER NOT NULL,
CUSTOMER VARCHAR(25) NOT NULL,
CONTACT_FIRST VARCHAR(15),
CONTACT_LAST VARCHAR(20),
...
PRIMARY KEY (CUST_NO)
);
</programlisting>
</para>
</formalpara>
</section>
<section xml:id="types-integer-bigint">
<info>
<title>BIGINT</title>
</info>
<indexterm><primary>BIGINT</primary></indexterm>
<para>BIGINT — это SQL-99-совместимый 64 битный целочисленный тип данных. Он доступен
только в 3-м диалекте. При использовании клиентом диалекта 1, передаваемое сервером
значение генератора усекается до 32-х битного целого (INTEGER). При подключении в
3-м диалекте значение генератора имеет тип BIGINT. </para>
<para>Числа типа BIGINT находятся в диапазоне -2<superscript>63</superscript> ..
2<superscript>63</superscript> - 1, или -9 223 372 036 854 775 808 .. 9 223 372
036 854 775 807. </para>
<para>Числа типа BIGINT могут быть заданы в шестнадцатеричном виде с 9 — 16
шестнадцатеричными цифрами. Более короткие шестнадцатеричные числа интерпретируются
как тип данных INTEGER. </para>
<formalpara>
<title>Примеры:</title>
<para>
<example>
<title>Использование типа BIGINT</title>
<para>
<programlisting language="sql">
CREATE TABLE WHOLELOTTARECORDS (
ID BIGINT NOT NULL PRIMARY KEY,
DESCRIPTION VARCHAR(32)
);
</programlisting>
</para>
</example>
</para>
</formalpara>
</section>
<section xml:id="types-integer-hex">
<title>Шестнадцатеричный формат для целых чисел</title>
<para>Начиная с Firebird 2.5, константы трех целочисленных типов можно указать в
шестнадцатеричном формате с помощью 9-16 шестнадцатеричных цифр для BIGINT или 1 до
8 цифр для INTEGER. Запись SMALLINT в шестнадцатеричном представлении не
поддерживается в явном виде, но Firebird будет прозрачно преобразовывать
шестнадцатеричное число в SMALLINT, если это необходимо, при условии что оно
попадает в допустимый диапазон положительных и отрицательных значений для
SMALLINT.</para>
<para>Использование и диапазоны значений чисел шестнадцатеричной нотации более подробно
описаны в ходе обсуждения <link linkend="common-expr-number-constants">целочисленных
констант</link> в главе под названием <citetitle>Общие элементы
языка</citetitle>.</para>
<formalpara>
<title>Примеры:</title>
<para>
<example>
<title>Использование целых чисел заданных шестнадцатеричном виде</title>
<para>
<programlisting language="sql">
INSERT INTO MYBIGINTS VALUES (
-236453287458723,
328832607832,
22,
-56786237632476,
0X6F55A09D42, -- 478177959234
0X7FFFFFFFFFFFFFFF, -- 9223372036854775807
0XFFFFFFFFFFFFFFFF, -- -1
0X80000000, -- -2147483648, т.е. INTEGER
0X080000000, -- 2147483648, т.е. BIGINT
0XFFFFFFFF, -- -1, т.е. INTEGER
0X0FFFFFFFF -- 4294967295, т.е. BIGINT
);
</programlisting>
</para>
</example>
</para>
</formalpara>
<para>Шестнадцатеричный INTEGER автоматически приводится к типу BIGINT перед вставкой в
таблицу. Однако это происходит после установки численного значения, так 0x80000000
(8 цифр) и 0x080000000 (9 цифр) будут сохранены в разных форматах. Значение
0x80000000 (8 цифр) будет сохранено в формате INTEGER, а 0x080000000 (9 цифр) как
BIGINT. </para>
</section>
</section>
<section xml:id="types-float">
<info>
<title>Типы данных с плавающей точкой</title>
</info>
<para>Типы данных с плавающей точкой хранятся в двоичном формате IEEE 745, который включает
в себя знак, показатель степени и мантиссу. Точность этого типа является динамической,
что соответствует физическому формату хранения, который составляет 4 байта для типа
FLOAT и 8 байт для типа DOUBLE PRECISION.</para>
<para>Учитывая особенности хранения чисел с плавающей точкой, этот тип данных не
рекомендуется использовать для хранения денежных данных. По тем же причинам не
рекомендуется использовать столбцы с данными такого типа в качестве ключей и применять к
ним ограничения уникальности.</para>
<para>При проверке данных столбцов с типами данных с плавающей точкой рекомендуется вместо
точного равенства использовать выражения проверки вхождения в диапазон, например
BETWEEN.</para>
<para>При использовании таких типов данных в выражениях рекомендуется крайне внимательно и
серьёзно подойти к вопросу округления результатов расчётов.</para>
<section xml:id="types-float-float">
<info>
<title>FLOAT</title>
</info>
<indexterm><primary>FLOAT</primary></indexterm>
<para>Данный тип данных обладает приблизительной точностью 7 цифр после запятой. Для
обеспечения надёжности хранения полагайтесь на 6 цифр.</para>
<section xml:id="types-float-float-precision">
<info>
<title>FLOAT с указанием точности</title>
</info>
<para>У типа FLOAT может быть указана точность в десятичных числах
<programlisting>
FLOAT(<replaceable>p</replaceable>)
</programlisting>
</para>
<para>Указанная точность <replaceable>p</replaceable> влияет на способ хранения
числа. <itemizedlist>
<listitem>
<para>0 <= p <= 7 — 32-битное одинарной точности (синоним типа
FLOAT)</para>
</listitem>
<listitem>
<para>p > 7 — 64-битное двойной точности (синоним типа DOUBLE
PRECISION)</para>
</listitem>
</itemizedlist>
</para>
<warning>
<para>FLOAT с указанием точности в десятичных числах не соответствует SQL
стандарту. Согласно стандарту точность для типа FLOAT указывается в двоичных
числах. В Firebird 4.0 это поведение изменено для согласования со
стандартом. Данный синтаксис не был документирован ранее. </para>
</warning>
</section>
</section>
<section xml:id="types-float-real">
<info>
<title>REAL</title>
</info>
<indexterm><primary>REAL</primary></indexterm>
<para>Тип REAL является синонимом типа FLOAT.</para>
</section>
<section xml:id="types-float-double">
<info>
<title>DOUBLE PRECISION</title>
</info>
<indexterm><primary>DOUBLE PRECISION</primary></indexterm>
<para>При хранении данных, предполагается приблизительная точность 15 цифр.</para>
</section>
<section xml:id="types-float-long_float">
<info>
<title>LONG FLOAT</title>
</info>
<indexterm><primary>LONG FLOAT</primary></indexterm>
<formalpara>
<title>Синтаксис:</title>
<para>
<literallayout class="monospaced">
LONG FLOAT[(<replaceable><precision></replaceable>)]
</literallayout>
</para>
</formalpara>
<para>Тип LONG FLOAT является синонимом типа DOUBLE PRECISION. У этого типа может быть
указана точность в десятичных числах. Указанная точность не влияет на способ
хранения — число всегда храниться как 64-битное двойной точности.</para>
<note>
<para>В Firebird 4.0 точность указывается в двоичных числах для согласования со
стандартом относительно типа FLOAT.</para>
</note>
<warning>
<para> Эти нестандартные имена типов устарели и могут быть удалены в будущей
версии.</para>
</warning>
</section>
</section>
<section xml:id="types-fixed">
<info>
<title>Типы данных с фиксированной точкой</title>
</info>
<para>Данные типы данных позволяют применять их для хранения денежных значений и
обеспечивают предсказуемость операций умножения и деления. </para>
<para>Firebird предлагает два типа данных с фиксированной точкой: NUMERIC и DECIMAL. В
соответствии со стандартом оба типа ограничивают хранимое число объявленным масштабом
(количеством чисел после запятой). При этом подход к тому, как ограничивается точность
для типов разный: для столбцов NUMERIC точность является такой, <quote>как
объявлено</quote>, в то время как DECIMAL столбцы могут получать числа, чья
точность, по меньшей мере, равна тому, что было объявлено. </para>
<para>Например, NUMERIC(4, 2) описывает число, состоящее в общей сложности из четырёх цифр,
включая 2 цифры после запятой; итого 2 цифры до запятой, 2 после. При записи в столбец с
этим типом данных значений 3,1415 в столбце NUMERIC(4, 2) будет сохранено значение 3,14. </para>
<para>Для данных с фиксированной точкой общим является форма декларации, например
NUMERIC(<replaceable>p</replaceable>, <replaceable>s</replaceable>). Здесь важно
понять, что в этой записи <replaceable>s</replaceable> — это масштаб, а не интуитивно
предсказываемое <quote>количество знаков после запятой</quote>. Для
<quote>визуализации</quote> механизма хранения данных запомните для себя процедуру: </para>
<para>
<itemizedlist spacing="compact">
<listitem>
<para>При сохранении в базу данных число умножается на
10<superscript>s</superscript> (10 в степени
<replaceable>s</replaceable>), превращаясь в целое; </para>
</listitem>
<listitem>
<para>При чтении данных происходит обратное преобразование числа. </para>
</listitem>
</itemizedlist>
</para>
<para>Способ физического хранения данных в СУБД зависит от нескольких факторов:
декларируемой точности, диалекта базы данных, типа объявления. </para>
<para>
<table xml:id="table-store-fixed">
<?dbfo keep-together='auto'?>
<title>Способ физического хранения чисел с фиксированной точкой</title>
<tgroup cols="4">
<colspec colname="colScale" colwidth="2*" align="left"/>
<colspec colname="colType" colwidth="3*" align="left"/>
<colspec colname="colDial01" colwidth="3*" align="left"/>
<colspec colname="colDial03" colwidth="3*" align="left"/>
<thead>
<row valign="middle">
<entry align="center">Точность</entry>
<entry align="center">Тип данных</entry>
<entry align="center">Диалект 1</entry>
<entry align="center">Диалект 3</entry>
</row>
</thead>
<tbody>
<row valign="middle">
<entry>1 - 4</entry>
<entry>NUMERIC</entry>
<entry>SMALLINT</entry>
<entry>SMALLINT</entry>
</row>
<row valign="middle">
<entry>1 - 4</entry>
<entry>DECIMAL</entry>
<entry>INTEGER</entry>
<entry>INTEGER</entry>
</row>
<row valign="middle">
<entry>5 - 9</entry>
<entry>NUMERIC и DECIMAL</entry>
<entry>INTEGER</entry>
<entry>INTEGER</entry>
</row>
<row valign="middle">
<entry>10 - 18</entry>
<entry>NUMERIC и DECIMAL</entry>
<entry>DOUBLE PRECISION</entry>
<entry>BIGINT</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<section xml:id="types-fixed-numeric">
<info>
<title>NUMERIC</title>
</info>
<indexterm><primary>NUMERIC</primary></indexterm>
<para>Формат объявления данных:
<programlisting>
NUMERIC(<replaceable>p</replaceable>, <replaceable>s</replaceable>)
</programlisting>
</para>
<para>В зависимости от точности <replaceable>p</replaceable> и масштаба
<replaceable>s</replaceable> СУБД хранит данные по-разному. </para>
<para>Приведём примеры того, как СУБД хранит данные в зависимости от формы их
объявления:
<programlisting>
NUMERIC(4) SMALLINT
NUMERIC(4,2) SMALLINT (data * 10<superscript>2</superscript>)
NUMERIC(10,4) DOUBLE PRECISION в 1-ом диалекте
BIGINT в 3-ем диалекте (data * 10<superscript>4</superscript>)
</programlisting>
</para>
<caution>
<para>Всегда надо помнить, что формат хранения данных зависит от точности. Например,
вы задали тип столбца NUMERIC(2, 2), предполагая, что диапазон значений в нем
будет -0.99...0.99. Однако в действительности диапазон значений в столбце будет
-327.68..327.67, что объясняется хранением типа данных NUMERIC(2, 2) в формате
SMALLINT. Фактически типы данных NUMERIC(4, 2), NUMERIC(3, 2) и NUMERIC(2, 2)
являются одинаковыми. То есть для реального хранения данных в столбце с типом
данных NUMERIC(2, 2) в диапазоне -0.99...0.99 для него надо создавать
ограничение. </para>
</caution>
</section>
<section xml:id="types-fixed-decimal">
<info>
<title>DECIMAL</title>
</info>
<indexterm><primary>DECIMAL</primary></indexterm>
<para>Формат объявления данных:
<programlisting>
DECIMAL(<replaceable>p</replaceable>, <replaceable>s</replaceable>)
</programlisting>
</para>
<para>Формат хранения данных в базе во многом аналогичен NUMERIC, хотя существуют
некоторые особенности, которые проще всего пояснить на примере. </para>
<para>Приведём примеры того, как СУБД хранит данные в зависимости от формы их
объявления:
<programlisting>
DECIMAL(4) INTEGER
DECIMAL(4,2) INTEGER (data * 10<superscript>2</superscript>)
DECIMAL(10,4) DOUBLE PRECISION в 1-ом диалекте
BIGINT в 3-ем диалекте (data * 10<superscript>4</superscript>)
</programlisting>
</para>
</section>
<section>
<title>Точность арифметических операций</title>
<para>Функции MIN, MAX, SUM, AVG работают со всеми точными числовыми типами. SUM и AVG
являются точными, если обрабатываемая запись имеет точный числовой тип, а
масштабированная сумма соответствует 64 битам: в противном случае возникает
исключение переполнения. SUM и AVG никогда не вычисляются с использованием
арифметики с плавающей запятой, если тип данных столбца не является приблизительным
числом.</para>
<para>Функции MIN и MAX для точного числового столбца возвращают точный числовой
результат, имеющий ту же точность и масштаб, что и столбец. SUM и AVG для точного
числового типа возвращает результат типа NUMERIC (18, S) или DECIMAL (18, S), где S
- масштаб столбца. (Стандарт SQL определяет масштаб результата в таких случаях, в то
время как точность SUM или AVG для столюцов с фиксированной точкой определяется
реализацией: мы определяем его как 18.)</para>
<para>Если два операнда OP1 и OP2 являются точными числами с масштабами S1 и S2
соответственно, то <code>OP1 + OP2</code> и <code>OP1 - OP2</code> являются точными
числами с точностью 18 и масштабом равному наибольшему из значений S1 и S2, тогда
как для <code>OP1 * OP2</code> и <code>OP1 / OP2</code> являются точными числами с
точностью 18 и шкалой <code>S1 + S2</code>. (Масштабы этих операций, кроме
разделения, определяются стандартом SQL. Точность всех этих операций и масштаб при
делении стандартом не регламентируются, а определяются реализацией: Firebird
определяет точность как 18, а масштаб деления как <code>S1 + S2</code>, такой же,
что определён стандартом в для умножения.) </para>
<para>Всякий раз, когда выполняется арифметические операции с точными числовыми типами,
в случае потери точности будет сообщено об ошибке переполнения, а не возвращёно
неправильное значение. В качестве примера, который может быть неочевидным для
читателя, если столбец DECIMAL (18,4) содержит наиболее отрицательное значение этого
типа, -922337203685477.5808, попытка разделить этот столбец на -1 будет сообщать об
ошибке переполнения, поскольку истинный результат превышает наибольшее положительное
значение, которое может быть представлено в типе, а именно
922337203685477.5807.</para>
<para>Если один операнд является точным числом, а другой приблизительным числом, то
результатом любого из четырех диадических операторов будет типа DOUBLE PRECISION. (В
стандарте говорится, что результат является приблизительным числом с точностью, по
крайней мере, такой же, как точность приблизительного числового операнда: Firebird
удовлетворяет этому требованию, всегда используя DOUBLE PRECISION, который является
максимальным приблизительным числовым типом, который предоставлен в
Firebird.)</para>
</section>
</section>
<section xml:id="types-datetime">
<info>
<title>Типы данных для работы с датой и временем</title>
</info>
<para>В СУБД Firebird для работы с данными, содержащими дату и время, используются типы
данных DATE, TIME, TIMESTAMP. В 3-м диалекте присутствуют все три вышеназванных типа
данных, а в 1-м для операций с датой и временем доступен только тип данных DATE, который
не тождественен типу данных DATE 3-го диалекта, а напоминает тип данных TIMESTAMP из
3-го диалекта. </para>
<note>
<para>В диалекте 1 тип DATE может быть объявлен как TIMESTAMP. Такое объявление является
рекомендуемым для новых баз данных в 1-м диалекте. </para>
</note>
<para>В типах DATETIME и TIME Firebird хранит секунды с точностью до десятитысячных долей.
Если вам необходима более низкая гранулярность, то точность может быть указана явно в
виде тысячных, сотых или десятых долей секунды в базах данных в 3 диалекте и ODS 11 и
выше.</para>
<note>
<title>Несколько полезных сведений о точности секунд</title>
<para>Временная часть типов TIME или TIMESTAMP представляет собой 4-байтный целое (WORD)
вмещающее значение времени с долями секунды, и хранящаяся как количество
десятитысячных долей секунды прошедших с полуночи. Фактическая точность значений
полученных из time(stamp) функций и переменных будет следующей: <itemizedlist>
<listitem>
<para>CURRENT_TIME — по умолчанию имеет точность до секунды, точность до
миллисекунд может быть указана следующим образом
<programlisting>CURRENT_TIME (0 | 1 | 2 | 3)</programlisting></para>
</listitem>
<listitem>
<para>CURRENT_TIMESTAMP — по умолчанию имеет точность до миллисекунды,
точность от секунд до миллисекунд может быть указана следующим образом
<programlisting>CURRENT_TIMESTAMP (0 | 1 | 2 | 3)</programlisting></para>
</listitem>
<listitem>
<para>Литерал 'NOW' имеет точность до миллисекунд;</para>
</listitem>
<listitem>
<para>Функции DATEADD и DATEDIFF поддерживают точность до десятых долей
миллисекунд.</para>
</listitem>
<listitem>
<para>Функция EXTRACT возвращает значения с точностью до десятых долей
миллисекунды для аргументов SECOND и MILLISECOND;</para>
</listitem>
</itemizedlist>
</para>
</note>
<section xml:id="types-datetime-date">
<info>
<title>DATE</title>
</info>
<indexterm><primary>DATE</primary></indexterm>
<para>В 3-м диалекте тип данных DATE, как это и следует предположить из названия, хранит
только одну дату без времени. В 1-м диалекте тип DATE эквивалентен типу TIMESTAMP и
хранит дату вместе со временем. </para>
<para>Допустимый диапазон хранения от 1 января 1 г. н.э. до 31 декабря 9999 года. </para>
<tip>
<para>В случае необходимости сохранять в 1 диалекте только значения даты, без
времени, при записи в таблицу добавляйте время к значению даты в виде литерала
'00:00:00.0000'. </para>
</tip>
</section>
<section xml:id="types-datetime-time">
<info>
<title>TIME</title>
</info>
<indexterm><primary>TIME</primary></indexterm>
<para>Этот тип данных доступен только в 3-м диалекте. Позволяет хранить время дня в
диапазоне от 00:00:00.0000 до 23:59:59.9999. </para>
<para>При необходимости получения времени из типа DATE в 1-м диалекте можно использовать
функцию EXTRACT. </para>
<example>
<info>
<title>Пример использования EXTRACT</title>
</info>
<para>
<programlisting language="sql">
EXTRACT (HOUR FROM DATE_FIELD)
EXTRACT (MINUTE FROM DATE_FIELD)
EXTRACT (SECOND FROM DATE_FIELD)
</programlisting>
</para>
</example>
<para>См. также описание функции <link linkend="internalfunc-func-datetime-extract"
>EXTRACT</link> в главе под названием <citetitle>Встроенные функции и
переменные</citetitle>. </para>
</section>
<section xml:id="types-datetime-timestamp">
<info>
<title>TIMESTAMP</title>
</info>
<indexterm><primary>TIMESTAMP</primary></indexterm>
<para>Этот тип данных хранит дату вместе со временем.</para>
</section>
<section xml:id="types-datetime-literals">
<title>Литералы даты и времени</title>
<para>Для записи литералов даты и времени в Firebird используются сокращенные
"C-style" выражения. Строковое представление даты и времени должно быть в
одном из разрешённых форматов.</para>
<formalpara>
<title>Синтаксис:</title>
<para>
<literallayout class="monospaced">
<replaceable><date_literal></replaceable> ::= DATE {<replaceable><date></replaceable> | {'NOW' | 'TODAY' | 'TOMORROW' | 'YESTERDAY'} }
<replaceable><time_literal></replaceable> ::= TIME {<replaceable><time></replaceable> | 'NOW'}
<replaceable><timestamp_literal></replaceable> ::= TIMESTAMP {<replaceable><timestamp></replaceable> | {'NOW' | 'TODAY' | 'TOMORROW' | 'YESTERDAY'} }
<replaceable><date></replaceable> ::=
[<replaceable>YYYY</replaceable><replaceable><p></replaceable>]<replaceable>MM</replaceable><replaceable><p></replaceable><replaceable>DD</replaceable> |
<replaceable>MM</replaceable><replaceable><p></replaceable><replaceable>DD</replaceable>[<replaceable><p></replaceable><replaceable>YYYY</replaceable>] |
<replaceable>DD</replaceable><replaceable><p></replaceable><replaceable>MM</replaceable>[<replaceable><p></replaceable><replaceable>YYYY</replaceable>] |
<replaceable>MM</replaceable><replaceable><p></replaceable><replaceable>DD</replaceable>[<replaceable><p></replaceable><replaceable>YY</replaceable>] |
<replaceable>DD</replaceable><replaceable><p></replaceable><replaceable>MM</replaceable>[<replaceable><p></replaceable><replaceable>YY</replaceable>]
<replaceable><time></replaceable> := <replaceable>HH</replaceable>[:<replaceable>mm</replaceable>[:<replaceable>SS</replaceable>[.<replaceable>NNNN</replaceable>]]]
<replaceable><timestamp></replaceable> ::= <replaceable><date></replaceable> <replaceable><time></replaceable>
<replaceable><p></replaceable> ::= <replaceable>whitespace</replaceable> | . | : | , | - | /
</literallayout>
</para>
</formalpara>
<para>
<table xml:id="types-datetime-literals-sesc" frame="all">
<?dbfo keep-together='auto'?>
<title>Описание формата даты и времени</title>
<tgroup cols="2">
<colspec colname="colArg" colnum="1" colwidth="2*" align="left"/>
<colspec colname="colDesc" colnum="2" colwidth="3*" align="left"/>
<thead>
<row valign="middle">
<entry align="center">Аргумент</entry>
<entry align="center">Описание</entry>
</row>
</thead>
<tbody>
<row valign="middle">
<entry><replaceable>datetime</replaceable></entry>
<entry><para>Строковое представление даты-времени.</para></entry>
</row>
<row valign="middle">
<entry><replaceable>date</replaceable></entry>
<entry><para>Строковое представление даты.</para></entry>
</row>
<row valign="middle">
<entry><replaceable>time</replaceable></entry>
<entry><para>Строковое представление времени.</para></entry>
</row>
<row valign="middle">
<entry><replaceable>YYYY</replaceable></entry>
<entry><para>Год из четырёх цифр.</para></entry>
</row>
<row valign="middle">
<entry><replaceable>YY</replaceable></entry>
<entry><para>Последние две цифры года (00-99).</para></entry>
</row>
<row valign="middle">
<entry><replaceable>MM</replaceable></entry>
<entry><para>Месяц. Может содержать 1 или 2 цифры (1-12 или 01-12).
В качестве месяца допустимо также указывать трёхбуквенное
сокращение или полное наименование месяца на английском
языке, регистр не имеет значение.</para>
</entry>
</row>
<row valign="middle">
<entry><replaceable>DD</replaceable></entry>
<entry><para>День. Может содержать 1 или 2 цифры (1-31 или
01-31).</para>
</entry>
</row>
<row valign="middle">
<entry><replaceable>HH</replaceable></entry>
<entry><para>Час. Может содержать 1 или 2 цифры (0-23 или
00-23).</para>
</entry>
</row>
<row valign="middle">
<entry><replaceable>mm</replaceable></entry>
<entry><para>Минуты. Может содержать 1 или 2 цифры (0-59 или
00-59).</para>
</entry>
</row>
<row valign="middle">
<entry><replaceable>SS</replaceable></entry>
<entry><para>Секунды. Может содержать 1 или 2 цифры (0-59 или
00-59).</para></entry>
</row>
<row valign="middle">
<entry><replaceable>NNNN</replaceable></entry>
<entry><para>Десятитысячные доли секунды. Может содержать от 1 до 4
цифр (0-9999).</para></entry>
</row>
<row valign="middle">
<entry><replaceable>p</replaceable></entry>
<entry><para>Разделитель, любой из разрешённых символов, лидирующие
и завершающие пробелы игнорируются.</para></entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>Правила: <itemizedlist spacing="compact">
<listitem>
<para>В формате Год-Месяц-День, год обязательно должен содержать 4
цифры;</para>
</listitem>
<listitem>
<para>Для дат в формате с завершающим годом, если в качестве разделителя дат
используется точка <quote>.</quote>, то дата интерпретируется в форме
День-Месяц-Год, для остальных разделителей она интерпретируется в форме
Месяц-День-Год;</para>
</listitem>
<listitem>
<para>Если год не указан, то в качестве года берётся текущий год;</para>
</listitem>
<listitem>
<para>Если указаны только две цифры года, то для получения столетия Firebird
использует алгоритм скользящего окна. Задача заключается в интерпретации
двухсимвольного значения года как ближайшего к текущему году в интервале
предшествующих и последующих 50 лет;</para>
</listitem>
<listitem>
<para>Если не указан один из элементов времени, то оно принимается равным
0.</para>
</listitem>
</itemizedlist>
</para>
<tip>
<para>Настоятельно рекомендуем в литералах дат использовать только формы с полным
указанием года в виде 4 цифр во избежание путаницы. </para>
</tip>
<formalpara>
<title>Примеры:</title>
<para>
<programlisting language="sql">
SELECT
date '04.12.2014' AS d1, -- DD.MM.YYYY
date '12-04-2014' AS d2, -- MM-DD-YYYY
date '12/04/2014' AS d3, -- MM/DD/YYYY
date '04.12.14' AS d4, -- DD.MM.YY
-- DD.MM в качестве года берётся текущий
date '04.12' AS d5,
-- MM/DD в качестве года берётся текущий
date '12/4' AS d6,
date '2014/12/04' AS d7, -- YYYY/MM/DD
date '2014.12.04' AS d8, -- YYYY.MM.DD
date '2014-12-04' AS d9, -- YYYY-MM-DD
-- дата на момент подготовки запроса
date 'NOW' AS d10,
-- дата на момент подготовки запроса
date 'TODAY' AS d11,
-- дата на 1 день меньше даты подготовки запроса
date 'YESTERDAY' AS d12,
-- дата на 1 день больше даты подготовки запроса
date 'TOMORROW' AS d13,
time '11:37' AS t1, -- HH:mm
time '11:37:12' AS t2, -- HH:mm:ss
time '11:31:12.1234' AS t3, -- HH:mm:ss.nnnn
-- время на момент подготовки запроса
time 'NOW' AS t4,
-- DD.MM.YYYY HH:mm
timestamp '04.12.2014 11:37' AS dt1,
-- MM/DD/YYYY HH:mm:ss
timestamp '12/04/2014 11:37:12' AS dt2,
-- DD.MM.YYYY HH:mm:ss.nnnn
timestamp '04.12.2014 11:31:12.1234' AS dt3,
-- дата и время на момент подготовки запроса
timestamp 'NOW' AS dt4,
-- дата на момент подготовки запроса, время 00:00:00
timestamp 'TODAY' AS dt5,
-- дата на 1 день меньше даты подготовки запроса, время 00:00:00
timestamp 'YESTERDAY' AS dt6,
-- дата на 1 день больше даты подготовки запроса, время 00:00:00
timestamp 'TOMORROW' AS dt7
FROM rdb$database
</programlisting>
</para>
</formalpara>
<note>
<para>Обратите внимание, что эти сокращённые выражения вычисляются сразу же во время
синтаксического анализа (подготовки запроса или компиляции процедуры, функции
или триггера).</para>
</note>
<warning>
<para>Не рекомендуем использовать сокращённые выражения для специальных строковых
литералов 'NOW', 'TODAY', 'TOMORROW', 'YESTERDAY'. Использование таких выражений
в компилируемом PSQL приводит к тому, что значение "замораживается" на момент
компиляции, и в результате возвращаются не актуальные значения. В Firebird 4.0
сокращённые выражения для таких строковых литералов будут запрещены, однако вы
по прежнему сможете использовать их при приведении типа оператором CAST.</para>
</warning>
<formalpara>
<title>См. также:</title>
<para>
<link xmlns:xlink="http://www.w3.org/1999/xlink"
linkend="types-cast-dateliteral">Преобразование строк в дату и время</link>.
</para>
</formalpara>
</section>
<section xml:id="types-datetime-operation">
<info>
<title>Операции, использующие значения даты и времени</title>
</info>
<para>Благодаря способу хранения даты и времени с этими типами возможны арифметические
операции вычитания из более поздней даты (времени) более раннюю. Дата представлена
количеством дней с "нулевой даты" – 17 ноября 1858 г. Время представлено
количеством секунд (с учётом десятитысячных долей), прошедших с полуночи. </para>
<para>
<table xml:id="types-datetime-tbl-operation" frame="all">
<?dbfo keep-together='auto'?>
<title>Арифметические операции для типов данных даты и времени</title>
<tgroup cols="4">
<colspec colname="colOp01" colnum="1" colwidth="1*" align="left"/>
<colspec colname="colOp" colnum="2" colwidth="1*" align="center"/>
<colspec colname="colOp02" colnum="3" colwidth="1*" align="left"/>
<colspec colname="colResult" colnum="4" colwidth="2*" align="justify"/>
<thead>
<row valign="middle">
<entry align="center">Операнд 1</entry>
<entry align="center">Оператор</entry>
<entry align="center">Операнд 2</entry>
<entry align="center">Результат</entry>
</row>
</thead>
<tbody>
<row valign="middle">
<entry>DATE</entry>
<entry>+</entry>
<entry>TIME</entry>
<entry>TIMESTAMP</entry>
</row>
<row valign="middle">
<entry>DATE</entry>
<entry>+</entry>
<entry>
<replaceable>n</replaceable>
</entry>
<entry>DATE, увеличенная на <replaceable>n</replaceable> целых дней
(дробная часть игнорируется).</entry>
</row>
<row valign="middle">
<entry>TIME</entry>
<entry>+</entry>
<entry>DATE</entry>
<entry>TIMESTAMP</entry>
</row>
<row valign="middle">
<entry>TIME</entry>
<entry>+</entry>
<entry>
<replaceable>n</replaceable>
</entry>
<entry>TIME, увеличенное на <replaceable>n</replaceable> секунд
(дробная часть учитывается)</entry>
</row>
<row valign="middle">
<entry>TIMESTAMP</entry>
<entry>+</entry>
<entry>
<replaceable>n</replaceable>
</entry>
<entry>TIMESTAMP, где дни увеличены на целую часть числа
<replaceable>n</replaceable>, плюс дробная часть числа
<replaceable>n</replaceable> (если указана) как количество
секунд в дне (с точностью до десятитысячных долей секунды).
</entry>
</row>
<row valign="middle">
<entry>DATE</entry>
<entry>-</entry>
<entry>DATE</entry>
<entry>Количество дней в интервале DECIMAL (9, 0)</entry>