Types décimales à virgule flottante
Les types de nombres décimaux à virgule flottante sont supportés à partir de Firebird 4.0.
Types numériques approximatifs
Comportement des opérations avec DECFLOAT
Longueur des littéraux DECFLOAT
DECFLOAT et fonctions Utilisation des fonctions conventionnelles Fonctions spéciales pour `DECFLOAT
Types de données en virgule flottante
Types de données à virgule fixe
Types de données pour travailler avec la date et l'heure
Conversion des types de données
Les types de nombres décimaux à virgule flottante sont supportés à partir de Firebird 4.0.
DECFLOAT
DECFLOAT
est un type numérique de la norme SQL:2016 qui stocke exactementdes nombres à virgule flottante. À la différence de DECFLOAT
, les types FLOAT
ou DOUBLE PRECISION
.fournissent une approximation binaire de la précision voulue.
Firebird, conformément à la norme IEEE 754-1985 (IEEE 754-2008), met en œuvre les typesDECIMAL64
(DECFLOAT(16)
) et DECIMAL128
(DECFLOAT(34)
).
Tous les calculs intermédiaires sont effectués à l’aide d’un code à 34 chiffres.valeurs.
“16” et “34” font référence à la précision maximale des chiffres décimaux.
Voir https://fr.wikipedia.org/wiki/IEEE_754 pour une description détaillée.
DECFLOAT[(precision)] precision ::= 16 | 34
Type | Précision maximale | Exponent minimal | Exposant maximal | Valeur la plus basse | Valeur maximale |
---|---|---|---|---|---|
|
16 |
-383 |
+384 |
1E-398 |
9.9..9E+384 |
|
34 |
-6143 |
+6144 |
1E-6176 |
9.9..9E+6144 |
Notez que bien que le plus petit exposant de DECFLOAT (16)
soit -383, la plus petite valeur a l’exposant -398, soit 15 chiffres de moins.Et de même, pour DECFLOAT (34)
, le plus petit exposant est -6143, mais la plus petite valeur a un exposant de degré -6176, soit 33 chiffres de moins.La raison en est que la précision a été "sacrifiée" afin de pouvoir stocker une valeur plus petite.
C’est le résultat de la façon dont la valeur est stockée : comme une valeur décimale de 16 ou 34 chiffres et l’exposant.Par exemple, 1.234567890123456e-383
est en fait stocké comme quotient 1234567890123456
et exposant -398
,et 1E-398
est retenu comme multiplicateur de 1
, exposant de degré -398
.
Le type DECFLOAT
doit être utilisé si vous avez besoin de calculer et de stocker des nombres avec une grande précision.
DECFLOAT
lors de la définition d’une tableCREATE TABLE StockPrice (
id INT NOT NULL PRIMARY KEY,
stock DECFLOAT(16),
...
);
DECFLOAT
en PSQLDECLARE VARIABLE v DECFLOAT(34);
DECFLOAT
Le comportement des opérations avec DECFLOAT
, en particulier le comportement des arrondis et des erreurs, peut être configuré avec la fonctioninstruction de contrôle SET DECFLOAT
DECFLOAT
Une valeur de type DECFLOAT
peut être définie par un littéral numérique en notation scientifique uniquement sila mantisse est constituée de 20 chiffres ou plus, ou l’exposant absolu est supérieur à 308. Sinon, ces littérauxsont interprétés comme DOUBLE PRECISION
.Les littéraux numériques exacts avec 40 chiffres ou plus — en fait 39 chiffres s’ils sont supérieurs à la valeur maximale de INT128 sont également traités comme DECFLOAT (34)
.
Il est également possible d’utiliser un littéral de chaîne de caractères et de le convertir explicitement dans le type souhaité DECFLOAT
.
La longueur des littéraux de type DECFLOAT
est limitée à 1024 caractères.Pour les valeurs plus longues, vous devrez utiliser la notation scientifique.Par exemple, la valeur 0.0<1020 zéros>11
ne peut pas être écrite comme un littéral, vous pouvez utiliser la notation scientifique similaire à la place : 1.1E-1022
.De même, 10<1022 zéros>0
peut s’écrire 1.0E1024
.
Les littéraux contenant plus de 34 chiffres significatifs sont arrondis en utilisant le mode d’arrondi DECFLOAT
défini pour la session.
DECFLOAT
et fonctionsUn certain nombre de fonctions scalaires standard peuvent être utilisées avec des expressions et des valeurs de type DECFLOAT
.Cela s’applique aux fonctions mathématiques suivantes :
|
|
|
|
|
|
|
|
|
|
Les fonctions d’agrégation SUM
, AVG
, MIN
et MAX
fonctionnent également avec le type DECFLOAT
.Toutes les fonctions d’agrégation statistique (telles que, mais sans s’y limiter, STDDEV
ou CORR
) peuvent traiter des données de type DECFLOAT
.
Firebird supporte 4 fonctions qui sont conçues spécifiquement pour supporter le type DECFLOAT
:
COMPARE_DECFLOAT
compare deux valeurs DECFLOAT
comme étant égales, différentes ou non ordonnées.
NORMALIZE_DECFLOAT
prend un seul argument DECFLOAT
et le retourne sous sa forme la plus simple.
QUANTIZE
prend deux arguments DECFLOAT
et retourne le premier argument mis à l’échelle en utilisant la deuxième valeur comme échantillon.
TOTALORDER
effectue une comparaison exacte de deux valeurs DECFLOAT
.
Les zéros en fin des valeurs décimales en virgule flottante sont conservés.Par exemple, 1,0 et 1,00 sont deux représentations différentes.Cela génère une sémantique de comparaison différente pour le type de données DECFLOAT
, comme indiqué ci-dessous.
Les zéros de fin sont ignorés dans les comparaisons.Par exemple, 1,0 est égal à 1,00.Par défaut, ce type de comparaison est utilisé pour l’indexation, le tri, le partitionnement des tables, l’évaluation des prédicats et d’autres fonctions — en bref, partout où la comparaison est effectuée implicitement ou dans les prédicats.
create table stockPrice (stock DECFLOAT(16));
insert into stockPrice
values (4.2);
insert into stockPrice
values (4.2000);
insert into stockPrice
values (4.6125);
insert into stockPrice
values (4.20);
commit;
select * from stockPrice where stock = 4.2;
-- Renvoie trois valeurs 4.2, 4.2000, 4.20
select * from stockPrice where stock > 4.20;
-- Retourne une valeur 4.6125
select * from stockPrice order by stock;
-- Retourne toutes les valeurs, 4.2, 4.2000, 4.20, 4.6125.
-- Les trois premières valeurs sont renvoyées dans un ordre indéfini.
Les zéros de queue sont pris en compte dans la comparaison.Par exemple, 1,0 > 1,00.Chaque valeur DECFLOAT
a un ordre dans la sémantique de comparaison TotalOrder.
Selon la sémantique TotalOrder, l’ordre des différentes valeurs est déterminé comme le montre l’exemple suivant :
-nan < -snan < -inf < -0.1 < -0.10 < -0 < 0 < 0.10 < 0.1 < inf < snan < nan
Important
|
Notez qu’un zéro négatif est inférieur à un zéro positif lors de la comparaison. TotalOrder |
Vous pouvez demander une comparaison TotalOrder dans les prédicats en utilisant la fonction intégrée TOTALORDER().
Pour les prix des actions, il peut être important de connaître l’exactitude des données.Par exemple, si les taux sont généralement indiqués avec cinq décimales et que le taux est de 4,2 $, il n’est pas clair si le prix est de 4,2000 $, 4,2999 $ ou quelque chose se situant entre ces deux valeurs.
create table stockPrice (stock DECFLOAT(16));
insert into stockPrice
values (4.2);
insert into stockPrice
values (4.2000);
insert into stockPrice
values (4.6125);
insert into stockPrice
values (4.20);
commit;
select * from stockPrice where TOTALORDER(stock, 4.2000) = 0;
-- Renvoie uniquement la valeur 4.2000
select * from stockPrice where TOTALORDER(stock, 4.20) = 1;
-- Renvoie deux valeurs 4.2 et 4.6125, ce qui est supérieur à 4.20
L’ordre dans lequel sont renvoyées des valeurs arithmétiques identiques comportant un nombre différent de zéros de fin n’est pas défini.Ainsi, ORDER BY
par la colonne DECFLOAT
avec les valeurs 1.0 et 1.00 renvoie deux valeurs dans un ordre aléatoire.De même, DISTINCT
renvoie soit 1.0 soit 1.00.
La bibliothèque fbclient version 4.0 a un support natif pour le type DECFLOAT
.Cependant, les anciennes versions de la bibliothèque client ne connaissent pas le type DECFLOAT
.Pour que les applications plus anciennes puissent gérer le type DECFLOAT
, vous pouvez configurer le mappage des valeurs DECFLOAT
vers d’autres types de données disponibles en utilisant l’attribut SET BIND
.
SET BIND OF DECFLOAT TO LEGACY;
-- Les valeurs des colonnes de type DECFLOAT seront converties en type DOUBLE PRECISION.
-- une autre option
SET BIND OF DECFLOAT TO DOUBLE PRECISION;
SET BIND OF DECFLOAT(16) TO CHAR;
-- Les valeurs de colonne de DECFLOAT(16) seront converties en CHAR(23).
SET BIND OF DECFLOAT(34) TO CHAR;
-- Les valeurs de colonne de DECFLOAT(34) seront converties en CHAR(42).
SET BIND OF DECFLOAT TO NUMERIC(18, 4);
-- Les valeurs des colonnes de DECFLOAT seront converties en NUMERIC(18, 4).
SET BIND OF DECFLOAT TO NATIVE;
-- Retourne les valeurs des colonnes de type DECFLOAT en type natif
Les différentes liaisons sont utiles si vous prévoyez d’utiliser des valeurs DECFLOAT
avec un ancien client qui ne supporte pas son propre format.Vous pouvez choisir entre des chaînes de caractères (précision parfaite, mais mauvaise prise en charge du traitement ultérieur), des valeurs à virgule flottante (prise en charge parfaite du traitement ultérieur, mais mauvaise précision) ou des nombres entiers mis à l’échelle (bonne prise en charge du traitement ultérieur et précision requise, mais plage de valeurs très limitée). Lorsqu’un outil tel que le client GUI universel est utilisé, le choix de la liaison à CHAR est approprié dans la plupart des cas.
Ces types de données permettent de les utiliser pour stocker des valeurs monétaires et fournissent une prévisibilité pour les opérations de multiplication et de division.
Firebird propose deux types de données à virgule fixe : NUMERIC
et DECIMAL
.Selon la norme, les deux types limitent le nombre stocké à une échelle déclarée (le nombre de décimales).Cependant, l’approche de la contrainte de précision est différente pour les types : pour les colonnes NUMERIC
, la précision est aussi quedéclaré", tandis que les colonnes `DECIMAL
peuvent recevoir des nombres dont la précision est au moins égale à ce qui a été déclaré.
Par exemple, NUMERIC(4, 2)
décrit un nombre composé d’un total de quatre chiffres dont 2 chiffres après la virgule ; total 2 chiffres avant la virgule, 2 après.Si vous écrivez une valeur de 3.1415 dans une colonne avec ce type de données, la colonne NUMERIC(4, 2)
conservera la valeur 3.14.
Pour les données à virgule fixe, ce qui est commun est la forme de la déclaration, par exemple NUMERIC(p, s). Ce qu’il faut comprendre ici, c’est que dans cette entrée, "est l’échelle, et non le "nombre de décimales" intuitivement prévu.Pour "visualiser" le mécanisme de stockage des données, mémorisez vous-même la procédure :
Lors de la sauvegarde dans la base de données, le nombre est multiplié par 10 (10s), ce qui le transforme en un nombre entier ;
Lorsque les données sont lues, le nombre est reconverti en un nombre entier.
La manière dont les données sont physiquement stockées dans le SGBD dépend de plusieurs facteurs : la précision déclarée, le dialecte de la base de données et le type de déclaration.
Précision | Type de données | Dialecte 1 | Dialecte 3 |
---|---|---|---|
1 - 4 |
NUMERIC |
SMALLINT |
SMALLINT |
1 - 4 |
DECIMAL |
INTEGER |
INTEGER |
5 - 9 |
NUMERIC ou DECIMAL |
INTEGER |
INTEGER |
10 - 18 |
NUMERIC ou DECIMAL |
DOUBLE PRECISION |
BIGINT |
19 - 38 |
NUMERIC ou DECIMAL |
INT128 |
INT128 |
NUMERIC
NUMERIC | NUMERIC(precision) | NUMERIC(precision, scale)
Paramètre ^^ | Description |
---|---|
precision |
Précision. Peut être compris entre 1 et 38.Le paramètre par défaut est 9. |
scale |
Scale. Peut aller de 0 à précision.Le paramètre par défaut est 0. |
En fonction de la précision precision et de l’échelle scale, le SGBD stocke les données différemment.
Voici des exemples de la manière dont un SGBD stocke les données en fonction de la forme sous laquelle elles sont déclarées :
NUMERIC(4) stored as SMALLINT (exact data) NUMERIC(4,2) SMALLINT (data * 102) NUMERIC(10,4) (Dialect 1) DOUBLE PRECISION (Dialect 3) BIGINT (data * 104) NUMERIC(38, 6) INT128 (data * 106)
Caution
|
N’oubliez jamais que le format de stockage des données dépend de leur précision.Par exemple, vous avez spécifié un type de colonne Ainsi, pour réellement stocker des données dans une colonne dont le type de données est NUMERIC(2, 2) dans la plage -0,99…0,99, vous devez créer une limite pour celle-ci. |
DECIMAL
DECIMAL | DECIMAL(precision) | DECIMAL(precision, scale)
Paramètre ^^ | Description |
---|---|
precision |
Précision. Peut être compris entre 1 et 38.Le paramètre par défaut est 9. |
scale |
Scale. Peut aller de 0 à précision.Le paramètre par défaut est 0. |
Le format de stockage de la base de données est largement similaire à celui de `NUMERIC', bien qu’il y ait certaines caractéristiques qui sont plus faciles à expliquer avec un exemple.
Voici des exemples de la manière dont la base de données stocke les données en fonction de la manière dont elles sont déclarées :
DECIMAL(4) stored as INTEGER (exact data) DECIMAL(4,2) INTEGER (data * 102) DECIMAL(10,4) (Dialect 1) DOUBLE PRECISION (Dialect 3) BIGINT (data * 104) DECIMAL(38, 6) INT128 (data * 106)
Les fonctions MIN
, MAX
, SUM
, AVG
fonctionnent avec tous les types numériques exacts.SUM
et AVG
sont exacts si l’entrée traitée est de type numérique exact et que la somme mise à l’échelle correspond à 64 ou 128 bits : sinon une exception de débordement se produit.SUM
et AVG
ne sont jamais calculés en utilisant l’arithmétique à virgule flottante, sauf si le type de données de la colonne est un nombre approximatif.
Les fonctions MIN
et MAX
pour une colonne numérique exacte retournent un résultat numérique exact avec la même précision et la même échelle que la colonne.SUM
et AVG
pour un type numérique exact retourne un résultat de type NUMERIC ({18 | 38}, S)
ou DECIMAL ({18 | 38}, S)
où S est l’échelle de la colonne.La norme SQL définit l’échelle du résultat dans de tels cas, tandis que la précision de SUM ou AVG pour les colonnes à virgule fixe est définie par l’implémentation : nous la définissons comme 18 ou 38 (si la précision de l’argument est 18 ou 38).
Si les deux opérandes OP1 et OP2 sont des nombres exacts d’échelle S1 et S2 respectivement, alors OP1 + OP2
et OP1 - OP2
sont des nombres exacts de précision 18 ou 38 (si l’un des arguments est de précision 38) et d’échelle égale au plus grand de S1 et S2, alors que pour OP1 * OP2
et OP1 / OP2
sont des nombres exacts de précision 18 ou 38 (si les arguments sont de précision 18 ou 38) et d’échelle S1 + S2
.Les échelles de ces opérations, sauf la division, sont définies par la norme SQL.La précision de toutes ces opérations et les échelles de division ne sont pas régies par la norme, mais sont définies par l’implémentation : Firebird définit la précision comme 18 ou 38 (si la précision de l’argument est 18 ou 38) et les échelles de division comme S1 + S2
, les mêmes que celles définies par la norme pour la multiplication.
Lorsque des opérations arithmétiques sont effectuées sur des types numériques exacts, une erreur de dépassement sera signalée si la précision est perdue, plutôt que de renvoyer une valeur incorrecte. Par exemple, si la colonne DECIMAL (18,4)
contient la valeur la plus négative de ce type, à savoir -922337203685477.5808, une tentative de division de cette colonne par -1 signalera une erreur de débordement car le résultat réel dépasse la plus grande valeur positive pouvant être représentée dans le type, à savoir 922337203685477.5807.
Si l’un des opérandes est un nombre exact et l’autre un nombre approximatif, le résultat de l’un des quatre opérateurs dyadiques sera de type DOUBLE PRECISION'.(La norme stipule que le résultat est un nombre approximatif avec au moins la même précision que l’opérande numérique approximatif : Firebird satisfait à cette exigence en utilisant toujours `DOUBLE PRECISION
, puisque ce type est le type numérique approximatif maximum que Firebird fournit).
Firebird utilise les types de données DATE
, TIME
et TIMESTAMP
pour gérer les données contenant la date et l’heure.Dans le dialecte 3, les trois types de données ci-dessus sont présents, tandis que dans le dialecte 1, seul le type de données DATE est disponible pour les opérations de date et d’heure, qui n’est pas identique au type de données DATE
du dialecte 3, mais est le type de données TIMESTAMP
du dialecte 3.
Note
|
Dans le dialecte 1, le type |
Dans les types TIMESTAMP
et TIME
, Firebird stocke les secondes avec des décimales.Si vous avez besoin d’une granularité inférieure, la précision peut être spécifiée explicitement en millièmes, centièmes ou dixièmes de seconde dans les bases de données en dialecte 3 et ODS 11 et plus.
Note
|
Quelques informations utiles sur l’exactitude des secondes
La partie temps des types
|
Les types de données avec support de fuseau horaire sont stockés comme des valeurs UTC (offset 0) en utilisant la structure TIME
ou TIMESTAMP
.+ deux octets supplémentaires pour les informations relatives au fuseau horaire (soit un décalage en minutes, soit un identifiant de fuseau horaire nommé).
Le stockage en UTC permet à Firebird d’indexer et de comparer deux valeurs dans des fuseaux horaires différents.
Le stockage en UTC présente quelques inconvénients :
Lorsque vous utilisez des zones nommées et que les règles de fuseau horaire de cette zone changent, l’heure en UTC reste la même, mais l’heure locale dans la zone nommée peut changer.
Pour le type de données TIME WITH TIME ZONE
, lors du calcul du décalage du fuseau horaire pour une zone nommée afin d’obtenir l’heure locale dans la zone, les règles en vigueur à partir du 1er janvier 2020 sont appliquées pour garantir une valeur stable.Cela peut conduire à des résultats inattendus ou déroutants.
DATE
Dans le dialecte 3, le type de données DATE
, comme son nom l’indique, ne stocke qu’une date sans heure.Dans le dialecte 1, le type DATE
est équivalent au type TIMESTAMP
et stocke la date en même temps que l’heure.
La plage de stockage acceptable va de 01.01.0001 à 31.12.9999.
Tip
|
S’il est nécessaire de sauvegarder uniquement les valeurs de la date dans 1 dialecte, sans l’heure, lors de l’écriture dans le tableau, ajoutez l’heure à la valeur de la date comme suitlittéral |
DATE
CRETE TABLE DataLog(
id BIGINT NOT NULL,
bydate DATE
);
...
AS
DECLARE BYDATE DATE;
BEGIN
...
Voir aussiEXTRACT,CURRENT_DATE,Litéraux de date.
TIME
TIME [{WITH | WITHOUT} TIME ZONE] EXTENDED TIME WITH TIME ZONE
Ce type de données n’est disponible que dans le dialecte 3.Permet de mémoriser l’heure du jour entre 00:00:00.0000 et 23:59:59.9999.Par défaut, le type TIME
ne contient aucune information sur le fuseau horaire.Pour que le type TIME
comprenne des informations sur le fuseau horaire, il doit être utilisé avec le modificateur WITH TIME ZONE
.
Important
|
L’option (pour plus d’informations, voir la rubrique SET BIND OF). |
TIME
CRETE TABLE DataLog(
id BIGINT NOT NULL,
bytime TIME WITH TIME ZONE
);
...
AS
DECLARE BYTIME TIME; -- pas de fuseau horaire
DECLARE BYTIME2 TIME WITHOUT TIME ZONE; -- pas de fuseau horaire
DECLARE BYTIME3 TIME WITH TIME ZONE; -- avec des informations sur le fuseau horaire
BEGIN
...
Voir aussiEXTRACT,AT,LOCALTIME,CURRENT_TIME,Conversion des Litéraux.
TIMESTAMP
TIMESTAMP [{WITH | WITHOUT} TIME ZONE] EXTENDED TIMESTAMP WITH TIME ZONE
Ce type de données enregistre un horodatage (date et heure) dans la plage 01.01.0001 00:00:00.0000 à 31.12.9999 23:59:59.9999.Par défaut, le type TIMESTAMP
ne contient aucune information sur le fuseau horaire.Pour que le type TIMESTAMP
comprenne des informations sur le fuseau horaire, il doit être utilisé avec le modificateur WITH TIME ZONE
.
Important
|
(pour plus d’informations, voir la rubrique SET BIND OF). |
CRETE TABLE DataLog(
id BIGINT NOT NULL,
bydate TIMESTAMP WITH TIME ZONE
);
...
AS
DECLARE BYDATE TIMESTAMP; -- pas de fuseau horaire
DECLARE BYDATE2 TIMESTAMP WITHOUT TIME ZONE; -- pas de fuseau horaire
DECLARE BYDATE3 TIMESTAMP WITH TIME ZONE; -- avec des informations sur le fuseau horaire
BEGIN
...
Le fuseau horaire de la session, comme son nom l’indique, peut être différent pour chaque connexion à la base de données.Il peut être défini avec le DPB isc_dpb_session_time_zone
, et sinon, il sera lu à partir du paramètre DefaultTimeZone
de la configuration firebird.conf.Si le paramètre DefaultTimeZone n’est pas défini, le fuseau horaire de la session sera le même que celui utilisé par le système d’exploitation dans lequel le processus Firebird est exécuté.
Le fuseau horaire de la session peut être modifié à l’aide de l’opérateur SET TIME ZONE
ou rétablissez la valeur d’origine avec `SET TIME ZONE LOCAL'.
Vous pouvez obtenir le fuseau horaire actuel de la session en utilisant la fonction RDB$GET_CONTEXT
avec les arguments 'SYSTEM' pour l’espace de noms et 'SESSION_TIMEZONE' comme nom de variable.
set time zone '-02:00';
select rdb$get_context('SYSTEM', 'SESSION_TIMEZONE') from rdb$database;
-- returns -02:00
set time zone 'America/Sao_Paulo';
select rdb$get_context('SYSTEM', 'SESSION_TIMEZONE') from rdb$database;
-- returns America/Sao_Paulo
Le fuseau horaire peut être spécifié comme une chaîne de caractères avec la région du fuseau horaire (par exemple, America/Sao_Paulo), ou commeDécalage hours:minutes
par rapport à GMT (par exemple -03:00).Une liste des fuseaux horaires régionaux et de leurs identifiants se trouve dans le tableau suivant RDB$TIME_ZONES. Les règles de conversion des fuseaux horaires régionaux en un décalage en minutes peuvent être obtenues en utilisant la procédure suivante RDB$TIME_ZONE_UTIL.TRANSITIONS.
{TIME | TIMESTAMP} WITH TIMEZONE
est considérée comme égale à une autre {TIME | TIMESTAMP} WITH TIMEZONE
, si leur conversion à UTC est égal à par exemple time '10:00 -02' = time '09:00 -03'
, car les deux temps sont équivalents time '12:00 GMT'
.Ceci est également vrai dans le contexte de la contrainte UNIQUE et pour le tri.
Par définition, les fuseaux horaires régionaux dépendent du temps (date et heure — ou horodatage) pour connaître son décalage UTC par rapport à GMT.Mais Firebird supporte également les fuseaux horaires régionaux dans les valeurs TIME WITH TIME ZONE
.
Lors de la construction d’une valeur TIME WITH TIME ZONE
à partir d’un littéral ou de sa conversion, la valeur UTC doit être calculée et ne peut pas être modifiée, donc la date actuelle ne peut pas être utilisée.Dans ce cas, la date fixe 2020-01-01
est utilisée.Ainsi, la comparaison de TIME WITH TIME ZONE
avec différents fuseaux horaires se fait de la même manière qu’ils représentent les valeurs de TIMESTAMP WITH TIME ZONE
à une date donnée.
Cependant, lors de la conversion entre les types TIMESTAMP
et TIME WITH TIME ZONE
, cette date fixe n’est pas utilisée,sinon, il peut y avoir des conversions étranges où la date actuelle a un décalage différent (en raison des changements d’heure d’été) que dans 2020-01-01
.Dans ce cas, la conversion de TIME WITH TIME ZONE
en TIMESTAMP WITH TIME ZONE
préserve une partie du temps (si possible).Par exemple, si la date actuelle est le 2020-05-03
, le décalage effectif dans le fuseau horaire America/Los_Angeles est de -420, et son décalage effectifdans 2020-01-01
est -480, mais cast(time '10:00:00 America/Los_Angeles' as timestamp with time zone)
donnera 20-05-03 10:00:00.0000 America/Los_Angeles
au lieu de corriger le timestamp.
Mais la date à laquelle l’heure d’été commence manque une heure, par exemple, pour le fuseau horaire America/Los_Angeles en 2021-03-14
il n’y a pas d’heure de 02:00:00
à 02:59:59
.Dans ce cas, la conversion est effectuée comme une construction littérale et l’heure est corrigée à la prochaine valeur valide.Par exemple, dans 2021-03-14
cast(time '02:10:00 America/Los_Angeles' as timestamp with time zone)
produira un résultat 2021-03-14 03:10:00.0000 America/Los_Angeles
.
Firebird utilise des expressions abrégées "style C" pour écrire les littéraux de date et d’heure.La représentation en chaîne de la date et de l’heure doit être dans l’un des formats autorisés.
<date_literal> ::= DATE <date> <time_literal> ::= TIME <time> <timestamp_literal> ::= TIMESTAMP <timestamp> <date> ::= [YYYY<p>]MM<p>DD | MM<p>DD[<p>YYYY] | DD<p>MM[<p>YYYY] | MM<p>DD[<p>YY] | DD<p>MM[<p>YY] <time> := HH[:mm[:SS[.NNNN]]] [<time zone>] <timestamp> ::= <date> <time> <time zone> ::= <time zone region> | [+/-] <hour displacement> [: <minute displacement>] <p> ::= whitespace | . | : | , | - | /
Argument | Description |
---|---|
datetime |
Représentation sous forme de chaîne de la date/heure. |
date |
Représentation sous forme de chaîne de la date. |
time |
Représentation sous forme de chaîne de l’heure. |
YYYY |
Une année à quatre chiffres. |
YY |
Les deux derniers chiffres de l’année (00-99). |
MM |
Mois. Peut contenir 1 ou 2 chiffres (1-12 ou 01-12). Comme un mois, il est également permis de spécifier une abréviation de trois lettres ou le nom complet du mois en anglais, le cas n’a pas d’importance. |
DD |
Jour. Peut contenir 1 ou 2 chiffres (1-31 ou 01-31). |
HH |
Heure. Peut contenir 1 ou 2 chiffres (0-23 ou 00-23). |
mm |
Minute. Peut contenir 1 ou 2 chiffres (0-59 ou 00-59). |
SS |
Seconde.Peut contenir 1 ou 2 chiffres (0-59 ou 00-59). |
NNNN |
Dix millièmes de seconde. Peut contenir de 1 à 4 chiffres (0-9999). |
p |
Le séparateur, tous les caractères autorisés, les espaces de début et de fin sont ignorés. |
time zone region |
Un des fuseaux horaires associés à la région. |
hour displacement |
Le décalage horaire de l’horloge est relatif à GMT. |
minute displacement |
Décalage horaire des minutes par rapport à GMT. |
Règles :
Dans le format Année-Mois-Jour, l’année doit nécessairement contenir 4 chiffres ;
Pour les dates au format fin d’année, si un point "." est utilisé comme séparateur de date, la date est interprétée comme Jour-Mois-Année, pour les autres séparateurs, elle est interprétée comme Mois-Jour-Année ;
Si une année n’est pas spécifiée, l’année en cours est prise comme année ;
Si seulement deux chiffres de l’année sont spécifiés, Firebird utilise un algorithme de fenêtre glissante pour obtenir le siècle. La tâche consiste à interpréter la valeur de l’année à deux chiffres comme étant la plus proche de l’année en cours dans l’intervalle des 50 années précédentes et suivantes ;
S’il y a un fuseau horaire ou un décalage horaire dans la représentation temporelle de la chaîne, le type littéral sera WITH TIME ZONE, sinon WITHOUT TIME ZONE ;
Si aucun élément de temps n’est spécifié, il est supposé être égal à 0.
Tip
|
Nous recommandons vivement de n’utiliser que des formulaires comportant l’année complète à 4 chiffres dans les littéraux de date afin d’éviter toute confusion. |
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 est considéré comme l'année en cours
date '04.12' AS d5,
-- MM/DD est considéré comme l'année en cours
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
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
-- HH:mm:ss.nnnn +hh
time '11:31:12.1234 +03' AS t4,
-- HH:mm:ss.nnnn +hh:mm
time '11:31:12.1234 +03:30' AS t5,
-- HH:mm:ss.nnnn tz
time '11:31:12.1234 Europe/Moscow' AS t5,
-- HH:mm tz
time '11:31 Europe/Moscow' AS t6,
-- 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,
-- YYYY-MM-DD HH:mm:ss.nnnn +hh:mm
timestamp '2014-12-04 11:31:12.1234 +03:00' AS dt4,
-- DD.MM.YYYY HH:mm:ss.nnnn tz
timestamp '04.12.2014 11:31:12.1234 Europe/Moscow' AS dt5
FROM rdb$database
Note
|
Notez que ces expressions abrégées sont évaluées immédiatement lors de l’analyse syntaxique (préparation d’une requête ou compilation d’une procédure, d’une fonction ou d’un déclencheur). Avant Firebird 4.0, les expressions abrégées étaient également autorisées pour les chaînes de caractères spéciales 'NOW', 'TODAY', 'TOMORROW', 'YESTERDAY'. L’utilisation de telles expressions dans le langage PSQL compilé aurait pour effet de "geler" la valeur au moment de la compilation et de renvoyer une valeur non valide.Par conséquent, dans Firebird 4.0, les expressions abrégées pour de tels littéraux de chaîne sont interdites, mais vous pouvez les utiliser pour les conversions de type CAST. |
En raison de la manière dont la date et l’heure sont stockées avec ces types, il est possible d’effectuer des opérations arithmétiques pour soustraire une date (heure) antérieure d’une date (heure) ultérieure.La date est représentée par le nombre de jours depuis la "date zéro" - le 17 novembre 1858.Le temps est représenté par le nombre de secondes (décimales comprises) écoulées depuis minuit.
Opérande 1 | Opérateur | Opérande 2 | Résultat |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
Valeur numérique |
|
|
|
|
|
|
|
|
|
|
|
Valeur numérique |
|
|
|
Valeur numérique |
|
|
|
Valeur numérique |
|
|
|
Valeur numérique |
|
|
|
|
Nombre de jours dans l’intervalle comme |
|
|
Valeur numérique |
|
|
|
|
Le nombre de secondes dans l’intervalle comme |
|
|
|
|
|
|
|
La valeur sans fuseau horaire est convertie en |
|
|
|
Le nombre de secondes entre les valeurs UTC est renvoyé comme suit |
|
|
|
Nombre de jours et de parties d’un jour dans un intervalle comme |
|
|
|
La valeur sans fuseau horaire est convertie en |
|
|
|
|
|
|
|
|
Une valeur de date/heure peut être soustraite de l’autre si :
Les deux valeurs sont du même type de date/heure ;
Le premier opérande est plus récent que le deuxième opérande.
Note
|
Dans le dialecte 1, le type |
Firebird 4 offre un certain nombre de fonctionnalités pour les informations sur les fuseaux horaires.
RDB$TIME_ZONES
Une table virtuelle avec une liste des fuseaux horaires supportés par Firebird.
Voir aussi RDB$TIME_ZONES
dans l’annexe "Tableaux du système".
RDB$TIME_ZONE_UTIL
Le paquet RDB$TIME_ZONE_UTIL
contient des procédures et des fonctions pour travailler avec les fuseaux horaires.
Vous trouverez une description détaillée du paquetage dans la section RDB$TIME_ZONE_UTIL
du chapitre Paquetages système.
Les fuseaux horaires changent fréquemment : bien entendu, lorsque cela se produit, il est conseillé de mettre à jour la base de données des fuseaux horaires dès que possible.
Firebird stocke les valeurs `WITH TIME ZONE' traduites en heure UTC. Supposons qu’une valeur soit créée en utilisant une base de données de fuseaux horaires et qu’une mise à jour ultérieure de cette base de données modifie les informations dans la plage de notre valeur stockée. Lorsque cette valeur est lue, elle sera renvoyée comme étant différente de la valeur qui était stockée à l’origine.
Firebird utilise IANA base de données des fuseaux horaires via la bibliothèque de l’ICU. La bibliothèque ICU fournie avec Firebird (Windows) ou installée dans un système d’exploitation POSIX peut parfois avoir une base de données de fuseaux horaires obsolète.
La base de données mise à jour peut être consultée à l’adresse suivante sur cette page du GitHub de FirebirdSQL.Le nom de fichier le.zip
désigne un ordre d’octet direct et est un fichier requis pour la plupart des architectures informatiques (compatibles Intel/AMD x86 ou x64), tandis que be.zip
désigne un ordre d’octet direct et est requis principalement pour les architectures informatiques RISC.Le contenu du fichier zip doit être extrait dans le sous-répertoire /tzdata
de l’installation Firebird, en écrasant les fichiers *.res
existants.
Note
|
|
Firebird possède des types CHAR
de longueur fixe et VARCHAR
de longueur variable pour gérer les données de type caractère.La taille maximale des données texte stockées dans ces types de données est de 32767 octets pour CHAR
et 32765 octets pour VARCHAR
.Le nombre maximum de caractères pouvant tenir dans cette taille dépend du jeu de caractères CHARACTER SET' utilisé.La séquence de tri spécifiée par la clause `COLLATE
n’a aucun effet sur ce maximum, bien qu’elle puisse affecter la taille maximale de tout index qui inclut une colonne.
Si aucun jeu de caractères n’est explicitement spécifié, le jeu de caractères par défaut spécifié lors de la création de l’objet texte de la base de données sera utilisé lors de la description de l’objet texte de la base de données.Si aucun jeu de caractères n’est explicitement spécifié et qu’il n’existe pas de jeu de caractères par défaut pour la base de données, le champ reçoit le jeu de caractères `CHARACTER SET NONE'.
Actuellement, tous les outils de développement modernes prennent en charge Unicode.Si vous devez utiliser des textes d’Europe de l’Est dans des champs de chaîne de données ou pour des alphabets plus exotiques, il est recommandé de travailler avec le jeu de caractères UTF8.Notez qu’il y a jusqu’à 4 octets par caractère dans ce jeu de caractères.Par conséquent, le nombre maximal de caractères dans les champs de caractères sera de 32765/4 = 8191.
Note
|
Notez que la valeur réelle du paramètre "octets par caractère" dépend de la gamme à laquelle appartient le caractère : les lettres anglaises prennent 1 octet, les lettres russes prennent 2 octets, les autres caractères peuvent prendre jusqu’à 4 octets. |
Le jeu de caractères UTF8 supporte la dernière version de la norme Unicode, jusqu’à 4 octets par caractère. Pour les bases de données internationales, il est donc recommandé d’utiliser cette implémentation du support Unicode dans Firebird.
NCHAR
Représente un type de données de caractères de longueur fixe avec un jeu de caractères ISO8859_1 prédéfini.
{NCHAR | NATIONAL {CHAR | CHARACTER}} [(length)]
Un synonyme est d’écrire CHAR NATIONAL
.
Un type de données similaire est disponible pour un type de chaîne de longueur variable : NATIONAL CHARACTER VARYING
.
Lorsqu’on traite des chaînes de caractères, il est important de se souvenir du jeu de caractères de la connexion client.Si le jeu de caractères est différent, la sortie des colonnes de chaînes de caractères est automatiquement recodée, à la fois lors du transfert des données du client vers le serveur, et dans le sens inverse, du serveur vers le client.En d’autres termes, il est parfaitement normal qu’une base de données soit créée avec le codage WIN1251
et que le client ait KOI8R
ou UTF8
dans les paramètres de connexion.
Le jeu de caractères `NONE' fait référence aux jeux de caractères spéciaux.Il se caractérise par le fait que chaque octet fait partie d’une chaîne de caractères, mais est stocké dans le système sans aucune indication du jeu de caractères auquel il appartient.C’est à l’application cliente de traiter ces données et il lui incombe d’interpréter correctement les caractères de ces champs.
Les jeux de caractères spéciaux comprennent également les `OCTETS'.Dans ce cas, les données sont traitées comme des octets, qui peuvent en principe ne pas être interprétés comme des caractères.`OCTETS' permet de stocker des données binaires et/ou les résultats de certaines fonctions Firebird.L’affichage correct des données stockées dans les champs `CHARACTER SET OCTETS' pour l’utilisateur devient également une préoccupation du côté client.Lorsque vous travaillez avec de telles données, n’oubliez pas que le SGBD n’a aucun contrôle sur leur contenu et qu’une exception peut être levée lorsque le code tente d’afficher des données binaires dans l’encodage souhaité.
Chaque jeu de caractères possède une séquence de tri (correspondance) par défaut (COLLATE
) qui détermine l’ordre de correspondance. Normalement, il assure un tri basé sur le code numérique des caractères et une correspondance de base entre les caractères majuscules et minuscules. Si un comportement est requis pour les chaînes de caractères qui n’est pas fourni par la séquence de tri par défaut, et qu’un tri alternatif approprié est supporté pour ce jeu de caractères, la clause COLLATE collation
peut être spécifiée dans la définition de la colonne.
La phrase COLLATE collation
peut être utilisée dans des contextes autres que la définition de la colonne. Pour les opérations de comparaison plus/moins, il peut être ajouté à la clause WHERE
de l’opérateur SELECT
. Si la sortie doit être triée dans une séquence alphabétique spécifique ou sans tenir compte de la casse et qu’il existe une correspondance appropriée, la phrase COLLATE
peut être utilisée dans la phrase ORDER BY
lorsque les lignes sont triées par champ de caractères, et dans la phrase GROUP BY
dans le cas d’opérations de groupe.
Pour une recherche insensible à la casse, vous pouvez utiliser la fonction UPPER
.
Pour une recherche insensible à la casse, vous pouvez utiliser la fonction UPPER
pour convertir l’argument de recherche et l’argumentet les chaînes de caractères recherchées en majuscules avant de tenter une correspondance.
...
WHERE UPPER(name) = UPPER(:flt_name)
Pour les chaînes de caractères dans un jeu de caractères pour lequel le tri insensible à la casse est disponible, vous pouvez simplement appliquerpour comparer directement l’argument de recherche et les chaînes de caractères.Par exemple, si vous utilisez le jeu de caractères WIN1251
, vous pouvez utiliser le tri insensible à la casse PXW_CYRL
à cette fin.
...
WHERE FIRST_NAME COLLATE PXW_CYRL >= :FLT_NAME
...
ORDER BY NAME COLLATE PXW_CYRL
Vous trouverez ci-dessous un tableau des séquences de tri possibles pour le jeu de caractères UTF8.
COLLATION | Commentaire |
---|---|
UCS_BASIC |
Le tri s’effectue en fonction de la position du caractère dans l’ordre alphabétique.table (binaire). |
UNICODE |
Le tri s’effectue selon l’algorithme UCA.(Unicode Collation Algorithm) (alphabétique). |
UTF-8 |
Par défaut, un mappage binaire est utilisé,identique à UCS_BASIC, qui a été ajouté pour les raisons suivantesla compatibilité avec la norme SQL. |
UNICODE_CI |
Triage sans tenir compte de la casse des caractères. |
UNICODE_CI_AI |
Triage sans casse et sans signes diacritiquespar ordre alphabétique. |
Exemple de tri de chaînes de caractères pour le jeu de caractères UTF8 sans caractères sensibles à la casse et sans diacritiques.
ORDER BY NAME COLLATE UNICODE_CI_AI
Lorsque l’on construit un index basé sur des champs de type chaîne, il faut tenir compte d’une restriction sur la longueur de la clé d’indexation.La longueur maximale de la clé d’indexation utilisée est égale à 1/4 de la taille de la page, c’est-à-dire de 1024 (pour une taille de page de 4096) à 8192 octets (pour une taille de page de 32768). La longueur maximale de la chaîne d’index est inférieure de 9 octets à la longueur maximale de la clé.Le tableau indique la longueur maximale de la chaîne d’index (en caractères) en fonction du format de la page et du jeu de caractères. Elle peut être calculée à l’aide de la formule suivante :
max_char_length = FLOOR((page_size / 4 – 9) / N),
où N
— nombre d’octets par représentation de caractère.
Taille de la page |
Longueur maximale dechaîne indexée pour le jeu de caractères, octet/symbole |
||||
---|---|---|---|---|---|
1 |
2 |
3 |
4 |
6 |
|
4096 |
1015 |
507 |
338 |
253 |
169 |
8192 |
2039 |
1019 |
679 |
509 |
339 |
16384 |
4087 |
2043 |
1362 |
1021 |
681 |
32768 |
8183 |
4091 |
2727 |
2045 |
1363 |
Note
|
Dans les codages insensibles à la casse ("`_CI"), un caractère dans l'index prendra 6 octets au lieu de 4, de sorte que la longueur maximale de la clé pour une page, par exemple pour une page de 4096 octets, est de 169 caractères. |
La séquence de tri (COLLATE) peut également affecter la longueur maximale d’une chaîne indexée.Une liste complète des jeux de caractères disponibles et des ordres de tri non standard est disponible en annexe.Jeux de caractères et ordres de tri.
CREATE DATABASE
, Ordre de tri, SELECT
, WHERE
, GROUP BY
, ORDER BY
BINARY
BINARY
est un type de données de longueur fixe permettant de stocker des données binaires.Si le nombre d’octets transférés est inférieur à la longueur déclarée, la valeur sera complétée par des zéros.Si aucune longueur n’est spécifiée, on suppose qu’elle est égale à un.
BINARY [(<length>)]
Note
|
Ce type est un alias du type `CHAR [(<length>)] CHARACTER SET OCTETS' et est rétrocompatible avec celui-ci. |
Tip
|
Ce type est bien adapté au stockage d’un identifiant unique obtenu à l’aide de la fonction [fblangref-scalarfuncs-gen-uuid]. |
CHAR
CHAR
est un type de données de longueur fixe.Si le nombre de caractères saisis est inférieur à la longueur déclarée, le champ sera complété par des espaces de fin.En général, le caractère de remplacement peut ne pas être un espace, cela dépend du jeu de caractères, par exemple, pour un jeu de caractères OCTETS
, c’est zéro.
Le nom complet du type de données est CHARACTER
, mais il n’est pas nécessaire d’utiliser les noms complets lorsqu’on travaille avec lui ; les outils de base de données comprennent très bien les noms courts des types de données caractères.
{CHAR | CHARACTER} [(length)] [CHARACTER SET <charset>] [COLLATE <collate>]
Si aucune longueur n’est spécifiée, on suppose qu’elle est égale à un.
Ce type de données de caractères peut être utilisé pour stocker des codes dans des répertoires dont la longueur est standard et d’une certaine "largeur".Un exemple de ceci serait un code postal en Russie - 6 caractères.
VARBINARY
VARBINARY
est un type permettant de stocker des données binaires de longueur variable.La taille réelle de la structure stockée est égale à la taille réelle des données plus les 2 octets dans lesquels la longueur du champ est spécifiée.
Nom complet BINARY VARYING
.
{VARBINARY | BINARY VARYING} (<length>)
Note
|
Ce type est un alias du type `VARCHAR (<length>) CHARACTER SET OCTETS' et est rétrocompatible avec celui-ci. |
DECLARE VARIABLE VAR1 VARBINARY(10);
CREATE TABLE INFO (
GUID BINARY(16),
ENCRYPT_KEY VARBINARY(100),
ICON BINARY VARYING(32000));
VARCHAR
VARCHAR
est un type de chaîne de base permettant de stocker des textes de longueur variable. La taille réelle de la structure stockée est donc égale à la taille réelle des données plus les 2 octets dans lesquels la longueur du champ est spécifiée.
Tous les caractères qui sont transmis de l’application client à la base de données sont traités comme des caractères significatifs, y compris les espaces de début et de fin.
Nom complet CHARACTER VARYING
.Une version abrégée de l’article est également disponible. CHAR VARYING
.
{VARCHAR | {CHAR | CHARACTER} VARYING} (length) [CHARACTER SET <charset>] [COLLATE <collate>]
Dans Firebird 3.0, un type de données logique complet a été introduit.
BOOLEAN
Le type de données BOOLEAN
(8 bits) conforme à SQL-2008 comprend diverses valeurs de vérité TRUE
et FALSE
.À moins que la restriction NOT NULL
ne soit définie, le type de données BOOLEAN
supporte également la valeur de vérité UNKNOWN
comme une valeur NULL
.La spécification ne fait pas de distinction entre une valeur NULL de ce type et une valeur de vérité UNKNOWN qui est le résultat d’un prédicat SQL, d’une condition de recherche ou d’une expression de type logique.Ces valeurs sont interchangeables et signifient la même chose.
Comme dans les autres langages de programmation, les valeurs de type BOOLEAN
peuvent être testées en valeurs de vérité implicites.Par exemple, "champ1 OR champ2" ou "NOT champ1" sont des expressions valables.
IS
Les prédicats peuvent utiliser l’opérateur logical IS [NOT]
pour la correspondance.Par exemple, field1 IS FALSE
, ou field1 IS NOT TRUE
.
Note
|
|
BOOLEAN
CREATE TABLE TBOOL (ID INT, BVAL BOOLEAN);
COMMIT;
INSERT INTO TBOOL VALUES (1, TRUE);
INSERT INTO TBOOL VALUES (2, 2 = 4);
INSERT INTO TBOOL VALUES (3, NULL = 1);
COMMIT;
SELECT * FROM TBOOL
ID BVAL ============ ======= 1 <true> 2 <false> 3 <null>
SELECT * FROM TBOOL WHERE BVAL
ID BVAL ============ ======= 1 <true>
FALSE
.SELECT * FROM TBOOL WHERE BVAL IS FALSE
ID BVAL ============ ======= 2 <false>
UNKNOWN
.SELECT * FROM TBOOL WHERE BVAL IS UNKNOWN
ID BVAL ============ ======= 3 <null>
SELECT ID, BVAL, BVAL AND ID < 2
FROM TBOOL
ID BVAL ============ ======= ======= 1 <true> <true> 2 <false> <false> 3 <null> <false>
DECLARE VARIABLE VAR1 BOOLEAN = TRUE;
-- Syntaxe acceptable, mais comme la comparaison
-- NULL, ne renverra jamais aucun des enregistrements
SELECT * FROM TBOOL WHERE BVAL = UNKNOWN
SELECT * FROM TBOOL WHERE BVAL <> UNKNOWN
Bien que BOOLEAN
ne puisse pas être converti en un autre type de données, à partir de la version 3.0.1, les chaînes 'true'
et 'false'
(insensibles à la casse) seront implicitement converties en BOOLEAN
dans les expressions de valeurs, par exemple
if (true > 'false') then ...
'False'
est converti en BOOLEAN
.Toute tentative d’utiliser les opérateurs logiques AND
, NOT
, OR
et IS
échouera.Par exemple, NOT 'False'
provoquera une erreur.
Un BOOLEAN
peut être explicitement converti en et depuis une chaîne de caractères en utilisant CAST
.La valeur UNKNOWN
n’est pas disponible lors de la conversion en chaîne.
Note
|
Autres remarques
|
BLOB
Les BLOB (Binary Large Objects) sont des structures complexes conçues pour stocker des données textuelles et binaires de longueur indéfinie, souvent de très grande taille.
BLOB [SUB_TYPE <subtype>] [SEGMENT SIZE <seg_length>] [CHARACTER SET <charset>] [COLLATE <collation name>]
BLOB (<seg_length>) BLOB (<seg_length>, <subtype>) BLOB (, <subtype>)
La spécification d’une taille de segment BLOB est en quelque sorte un atavisme, qui remonte à l’époque où les applications destinées à travailler avec des données BLOB étaient écrites en C (Embedded SQL) à l’aide de GPRE.Actuellement, la taille du segment lors de l’utilisation de données BLOB est déterminée par la partie client, et la taille du segment peut dépasser la taille de la page de données.
Le sous-type BLOB reflète la nature des données enregistrées dans la colonne.Firebird fournit deux sous-types prédéfinis pour le stockage des données utilisateur :
Si aucun sous-type n’est spécifié, les données sont considérées comme non typées et la valeur du sous-type est supposée être 0.L’alias du sous-type 0 est BINARY
.Ce sous-type indique que les données se présentent sous la forme d’un fichier ou d’un flux binaire (image, son, vidéo, fichiers de traitement de texte, PDF, etc.)
Le sous-type 1 a un alias TEXT
, qui peut être utilisé au lieu de spécifier un numéro de sous-type.Par exemple, BLOB SUBTYPE TEXT
.Il s’agit d’un sous-type spécialisé qui est utilisé pour stocker des données textuelles de grande taille.Pour le sous-type de texte BLOB
, un jeu de caractères et un ordre de tri COLLATE
peuvent être spécifiés, comme pour un champ de caractères.
Il est également possible d’ajouter des sous-types de données personnalisés, pour lesquels un intervalle de -1 à -32768 est réservé.Les sous-types personnalisés avec des nombres positifs ne sont pas supportés car Firebird utilise des nombres supérieurs à 2 pour les sous-types de métadonnées internes.
La taille maximale du champ BLOB est limitée à 4 Go et ne dépend pas de la variante du serveur, 32 bits ou 64 bits (il existe des compteurs de 4 octets dans les structures internes liées aux BLOB). Pour une taille de page de 4096, la taille maximale du champ BLOB est légèrement inférieure à 2 Go.
Les BLOB texte de n’importe quelle longueur et avec n’importe quel jeu de caractères (y compris multi-octets) peuvent être utilisés avec presque toutes les fonctions et opérateurs intégrés.
Les opérateurs suivants sont entièrement pris en charge :
= |
(affectation) |
=, <>, <, <=, >, >= |
(comparaison) |
|
(concaténation) |
|
|
|
|
|
|
Les opérateurs suivants sont partiellement pris en charge :
Une erreur se produit si le second argument est supérieur ou égal à 32Kb.
|
|
|
|
Les suggestions d’agrégation ne fonctionnent pas avec le contenu du champ lui-même, mais avec l’ID BLOB. En dehors de cela, il y a quelques bizarreries :
|
produit par erreur des valeurs NULL multiples si elles sont présentes |
|
— |
|
fusionne les mêmes lignes si elles sont adjacentes l’une à l’autre, mais ne le fait pas si elles sont éloignées l’une de l’autre |
Par défaut, un enregistrement régulier est créé pour chaque BLOB
stocké sur une page de données dédiée (page de données). Si un BLOB entier tient sur cette page, on l’appelle un `BLOB' de niveau 0. Le numéro de cet enregistrement spécial est stocké dans l’enregistrement de la table et occupe 8 octets.
Si BLOB
ne tient pas sur une seule page de données (data page), son contenu est placé sur des pages séparées entièrement allouées pour lui (blob page), et les numéros de ces pages sont placés dans l’enregistrement de BLOB
. Il s’agit d’une BLOB
de niveau 1.
Si un tableau de numéros de pages de données d’un BLOB
ne tient pas sur une page de données, alors il est placé sur des pages séparées (blob pages) et l’enregistrement d’un BLOB
contient les numéros de ces pages. Il s’agit d’un `BLOB' de niveau 2.
Les niveaux supérieurs à 2 ne sont pas pris en charge.
Le support des tableaux dans Firebird est une extension du modèle relationnel traditionnel.La prise en charge des tableaux est une extension du modèle relationnel traditionnel.Les tableaux dans Firebird sont basés sur des champs BLOB.Les tableaux peuvent être unidimensionnels ou multidimensionnels.
CREATE TABLE SAMPLE_ARR (
ID INTEGER NOT NULL PRIMARY KEY,
ARR_INT INTEGER [4]);
Cela créera une table avec un champ de type tableau de quatre entiers.Les indices de ce tableau sont de 1 à 4.
Par défaut, les dimensions commencent à 1.La syntaxe suivante doit être utilisée pour définir la limite supérieure et inférieure des valeurs d’index :
[<lower>:<upper>]
L’ajout d’une nouvelle dimension dans la syntaxe se fait avec une virgule.Un exemple de création d’une table avec un tableau de dimension deux, où la limite inférieure des valeurs commence par zéro :
CREATE TABLE SAMPLE_ARR2 (
ID INTEGER NOT NULL PRIMARY KEY,
ARR_INT INTEGER [0:3, 0:3]);
Le SGBDR ne fournit pas beaucoup d’outils pour manipuler le contenu des tableaux.La base de données employee.fdb, qui se trouve dans la distribution Firebird, contient un exemple de procédure stockée qui montre comment manipuler des tableaux.Voici le texte de la procédure stockée :
CREATE OR ALTER PROCEDURE SHOW_LANGS (
CODE VARCHAR(5),
GRADE SMALLINT,
CTY VARCHAR(15))
RETURNS (
LANGUAGES VARCHAR(15))
AS
DECLARE VARIABLE I INTEGER;
BEGIN
I = 1;
WHILE (I <= 5) DO
BEGIN
SELECT LANGUAGE_REQ[:I]
FROM JOB
WHERE (JOB_CODE = :CODE)
AND (JOB_GRADE = :GRADE)
AND (JOB_COUNTRY = :CTY)
AND (LANGUAGE_REQ IS NOT NULL))
INTO :LANGUAGES;
IF (:LANGUAGES = '') THEN
/* IMPRIME 'NULL' AU LIEU DE BLANCS */
LANGUAGES = 'NULL';
I = I +1;
SUSPEND;
END
END
Si les caractéristiques ci-dessus sont suffisantes pour vos besoins, vous pouvez très bien utiliser les tableaux pour vos projets.Il n’y a actuellement aucune amélioration dans les mécanismes de gestion des tableaux du SGBD.
SQL_NULL
Ce type de données ne contient pas de données, mais seulement un état : NULL
ou NOT NULL
.De plus, ce type de données ne peut pas être utilisé lors de la déclaration de champs de table, de variables PSQL, utilisés dans les descriptions de paramètres.Ce type de données a été ajouté pour améliorer la prise en charge des paramètres non typés dans le prédicat IS NULL
.Ce problème se produit lors de l’utilisation de filtres excluables
lors de l’écriture de requêtes du type suivant :
WHERE col1 = :param1 OR :param1 IS NULL
Une fois traitée, au niveau de l’API, la demande aura l’apparence suivant
WHERE col1 = ? OR ? IS NULL
Dans ce cas, le développeur traite :param1
comme une variable qui est utilisée deux fois, alors qu’au niveau de l’API, la requête contient deux paramètres distincts et indépendants.En plus de cela, le serveur ne peut pas déterminer le type du second paramètre car il est associé à IS NULL
.
C’est pour résoudre le ` ? IS NULL` a été ajouté ce type de données spécial SQL_NULL.
Après l’introduction de ce type de données spécial, lors de l’envoi d’une requête et de ses paramètres au serveur, le schéma suivant sera appliqué : l’application transmet les requêtes paramétrées au serveur sous la forme “?”.Il est donc impossible de fusionner une paire de paramètres "identiques" en un seul.Ainsi, par exemple, pour deux filtres (deux paramètres nommés), quatre paramètres positionnels doivent être passés (en supposant en outre que le lecteur a une certaine familiarité avec l’API de Firebird) :
SELECT
SH.SIZE, SH.COLOUR, SH.PRICE
FROM SHIRTS SH
WHERE (SH.SIZE = ? OR ? IS NULL)
AND (SH.COLOUR = ? OR ? IS NULL)
Après l’exécution de isc_dsql_describe_bind()
, le sqltype des 2ème et 4ème paramètres est défini comme SQL_NULL.Comme indiqué ci-dessus, le serveur Firebird ne dispose d’aucune information sur leur relation avec les 1er et 3ème paramètres — c’est entièrement la prérogative du programmeur.Une fois que les valeurs des 1er et 3e paramètres ont été définies (ou mises à NULL) et que la requête est préparée, chaque paire de XSQLVARs doit être remplie comme suit :
Premier paramètre (comparaison de valeurs) : définition de *sqldata
à la valeur passée et de *sqlind
à 0
(pour NOT NULL
) ;
Deuxième paramètre (vérification de NULL) : mettre *sqldata
à null
(pointeur nul, pas SQL NULL
) et *sqlind
à 0 (pour NOT NULL
).
Les deux paramètres (vérification de NULL) : mettre *sqldata
à null
(pointeur nul, pas SQL NULL
) et *sqlind
à -1 (indication NULL
).
En d’autres termes, la valeur du paramètre de comparaison est toujours fixée comme d’habitude.Le paramètre SQL_NULL
est également défini, sauf si sqldata
est passé comme null
.
Lorsque vous écrivez une expression ou que vous spécifiez, par exemple, des conditions de comparaison, vous devez essayer d’utiliser des Types de données compatibles.Si vous devez utiliser des données mixtes de différents types, il est conseillé d’effectuer d’abord les conversions de type, puis d’effectuer les opérations.
Lorsque l’on envisage des conversions de type dans Firebird, il faut prêter une grande attention au dialecte dans lequel se trouve la base de données.
Lorsqu’une conversion explicite d’un type à un autre est nécessaire, la fonction CAST
est utilisée.
CAST (<expression> | NULL AS <data_type>) <data_type> ::= <datatype> | [TYPE OF] domain | TYPE OF COLUMN relname.colname <datatype> ::= <scalar_datatype> | <blob_datatype> | <array_datatype>
scalar_datatype ::= Voir. Syntaxe des types de données scalaires
blob_datatype ::= Voir. Syntaxe des types de données BLOB
array_datatype ::= Voir. Syntaxe des tableaux
Lors de la conversion vers un domaine, les restrictions déclarées pour celui-ci, telles que NOT NULL
ou celles décrites dans CHECK
, sont prises en compte et si <expression>
échoue, la conversion échouera.Si en plus TYPE OF
est spécifié (conversion en type de base), la conversion ignore toute restriction de domaine.Si TYPE OF
est utilisé avec le type [VAR]CHAR
, le jeu de caractères et le tri sont préservés.
Lors de la conversion vers un type de colonne, il est permis d’utiliser une spécification de colonne de table ou de vue.Seul le type de colonne lui-même est utilisé ; dans le cas des types de chaînes de caractères, cela inclut également le jeu de caractères, mais pas le tri.Les contraintes et les valeurs par défaut de la colonne d’origine ne s’appliquent pas.
CREATE TABLE TTT (
S VARCHAR (40)
CHARACTER SET UTF8 COLLATE UNICODE_CI_AI);
COMMIT;
/* J'ai beaucoup d'amis (suédois)*/
SELECT
CAST ('Jag har manga vanner' AS TYPE OF COLUMN TTT.S)
FROM RDB$DATABASE;
CAST
Type d’origine | Cast |
---|---|
Type numérique |
Type numérique, |
|
|
|
|
|
|
|
|
Pour convertir des types de données de type chaîne en type BOOLEAN, l’argument chaîne doit être l’un des littéraux prédéfinis du type logique ('true'
ou 'false'
).
Important
|
Lors de la conversion des types, il faut tenir compte de la possibilité de perte partielle de données, par exemple lors de la conversion du type de données |
Pour convertir des types de données de type chaîne en DATE
, TIME
ou TIMESTAMP
, l’argument chaîne doit être soit un des littéraux de date et d’heure prédéfinis, soit une représentation de la date dans l’un des formats autorisés.
<date_literal> ::= [YYYY<p>]MM<p>DD | MM<p>DD[<p>YYYY] | DD<p>MM[<p>YYYY] | MM<p>DD[<p>YY] | DD<p>MM[<p>YY] <time_literal> := HH[:mm[:SS[.NNNN]]] <datetime_literal> ::= <date_literal> <time_literal> <time zone> ::= <time zone region> | [+/-] <hour displacement> [: <minute displacement>] <p> ::= whitespace | . | , | - | / position: absolute; float: left;
Argument | Description |
---|---|
datetime_literal |
Les littéraux date-heure. |
date_literal |
Date littérale. |
time_literal |
Le temps littéral. |
YYYY |
Une année à quatre chiffres. |
YY |
Les deux derniers chiffres de l’année (00-99). |
MM |
Mois.Peut contenir 1 ou 2 chiffres (1-12 ou 01-12). Le mois peut également être une abréviation de trois lettres ou le nom complet du mois en anglais, sans tenir compte de la casse. |
DD |
Jour.Peut contenir 1 ou 2 chiffres (1-31 ou 01-31). |
HH |
Heure.Peut contenir 1 ou 2 chiffres (0-23 ou 00-23). |
mm |
Minute.Peut contenir 1 ou 2 chiffres (0-59 ou 00-59). |
SS |
Secondes.Peut contenir 1 ou 2 chiffres (0-59 ou 00-59). |
NNNN |
Dix millièmes de seconde.Peut contenir de 1 à 4 chiffres (0-9999). |
p |
Séparateur, n’importe lequel des caractères autorisés, les espaces avant et arrière sont ignorés. |
time zone region |
Un des fuseaux horaires associés à la région |
hour displacement |
Décalage horaire de l’horloge par rapport à GMT |
minute displacement |
Décalage horaire pour les minutes par rapport à GMT |
Les littéraux | Valeur | Type de données pour le dialecte 1 | Type de données pour le dialecte 3 |
---|---|---|---|
|
Date et heure actuelles |
TIMESTAMP |
TIMESTAMP |
|
Date actuelle |
TIMESTAMP (avec un temps nul) |
DATE (date uniquement) |
|
Date de demain |
TIMESTAMP (avec un temps nul) |
DATE (date uniquement) |
|
Date d’hier |
TIMESTAMP (avec un temps nul) |
DATE (date uniquement) |
Règles :
Au format Année-Mois-Jour, l’année doit obligatoirement comporter 4 chiffres ;
Pour les dates au format fin d’année, si un point “.” est utilisé comme séparateur de date, la date est interprétée comme Jour-Mois-Année, pour les autres séparateurs, elle est interprétée comme Mois-Jour-Année ;
Si aucune année n’est spécifiée, l’année en cours est prise comme année ;
Si seulement deux chiffres de l’année sont spécifiés, Firebird utilise l’algorithme de la fenêtre glissante pour obtenir le siècle. La tâche consiste à interpréter la valeur de l’année à deux caractères comme étant la plus proche de l’année en cours dans l’intervalle des 50 années précédentes et suivantes ;
Si aucun élément de temps n’est spécifié, il est supposé être égal à 0.
Lors de l’utilisation de CAST() pour convertir des littéraux de chaîne en type date/heure, la valeur est toujours calculée au moment de l’exécution.
Lors de la conversion de chaînes de caractères avec des valeurs de date et d’heure prédéfinies en type TIMESTAMP, la précision est de 3 décimales (millisecondes).
Tip
|
Nous recommandons vivement de n’utiliser que des formulaires comportant l’année complète à 4 chiffres dans les littéraux de date afin d’éviter toute confusion. |
SELECT
CAST('04.12.2014' AS DATE) AS d1, -- DD.MM.YYYY
CAST('12-04-2014' AS DATE) AS d2, -- MM-DD-YYYY
CAST('12/04/2014' AS DATE) AS d3, -- MM/DD/YYYY
CAST('04.12.14' AS DATE) AS d4, -- DD.MM.YY
-- DD.MM année en cours
CAST('04.12' AS DATE) AS d5,
-- MM/DD année en cours
CAST('12/4' AS DATE) AS d6,
CAST('2014/12/04' AS DATE) AS d7, -- YYYY/MM/DD
CAST('2014.12.04' AS DATE) AS d8, -- YYYY.MM.DD
CAST('2014-12-04' AS DATE) AS d9, -- YYYY-MM-DD
CAST('11:37' AS TIME) AS t1, -- HH:mm
CAST('11:37:12' AS TIME) AS t2, -- HH:mm:ss
CAST('11:31:12.1234' AS TIME) AS t3, -- HH:mm:ss.nnnn
-- HH:mm:ss.nnnn +hh
CAST('11:31:12.1234 +03' AS TIME WITH TIME ZONE) AS t4,
-- HH:mm:ss.nnnn +hh:mm
CAST('11:31:12.1234 +03:30' AS TIME WITH TIME ZONE) AS t5,
-- HH:mm:ss.nnnn tz
CAST('11:31:12.1234 Europe/Moscow' AS TIME WITH TIME ZONE) AS t5,
-- HH:mm tz
CAST('11:31 Europe/Moscow' AS TIME WITH TIME ZONE) AS t6,
-- DD.MM.YYYY HH:mm
CAST('04.12.2014 11:37' AS TIMESTAMP) AS dt1,
-- MM/DD/YYYY HH:mm:ss
CAST('12/04/2014 11:37:12' AS TIMESTAMP) AS dt2,
-- DD.MM.YYYY HH:mm:ss.nnnn
CAST('04.12.2014 11:31:12.1234' AS TIMESTAMP) AS dt3,
-- YYYY-MM-DD HH:mm:ss.nnnn +hh:mm
CAST('2014-12-04 11:31:12.1234 +03:00' AS TIMESTAMP WITH TIME ZONE) AS dt4,
-- DD.MM.YYYY HH:mm:ss.nnnn tz
CAST('04.12.2014 11:31:12.1234 Europe/Moscow' AS TIMESTAMP WITH TIME ZONE) AS dt5,
CAST('now' AS DATE) AS d_now,
CAST('now' AS TIMESTAMP) AS ts_now,
CAST('now' AS TIMESTAMP WITH TIME ZONE) AS ts_now_tz,
CAST('today' AS DATE) AS d_today,
CAST('today' AS TIMESTAMP) AS ts_today,
CAST('today' AS TIMESTAMP WITH TIME ZONE) AS ts_today_tz,
CAST('tomorrow' AS DATE) AS d_tomorrow,
CAST('tomorrow' AS TIMESTAMP) AS ts_tomorrow,
CAST('tomorrow' AS TIMESTAMP WITH TIME ZONE) AS ts_tomorrow_tz,
CAST('yesterday' AS DATE) AS d_yesterday,
CAST('yesterday' AS TIMESTAMP) AS ts_yesterday,
CAST('yesterday' AS TIMESTAMP WITH TIME ZONE) AS ts_yesterday_tz
FROM rdb$database
Note
|
Comme |
CAST('NOW' AS TIMESTAMP)
pour mesurer la durée d’exécution du codeEXECUTE BLOCK
RETURNS (ms BIGINT)
AS
DECLARE VARIABLE t1 TIME;
DECLARE VARIABLE n BIGINT;
BEGIN
t1 = CAST('now' AS TIMESTAMP);
/* Long fonctionnement */
SELECT COUNT(*) FROM rdb$types, rdb$types, rdb$types INTO n;
/*======*/
ms = DATEDIFF(MILLISECOND FROM t1 TO CAST('now' AS TIMESTAMP));
SUSPEND;
END
Dans le dialecte 3, aucune conversion implicite de données n’est possible, ici la fonction CAST
doit être spécifiée pour traduire explicitement un type vers un autre.Toutefois, cela ne s’applique pas à l’opération de concaténation, dans laquelle tous les autres Types de données seront implicitement convertis en un type de caractère.
En utilisant le dialecte 1, de nombreuses expressions effectuent une conversion implicite d’un type vers un autre sans utiliser la fonction CAST
.Par exemple, dans une expression de sélection en dialecte 1, vous pouvez écrire :
WHERE DOC_DATE < '31.08.2014'
et la conversion de la chaîne en date se fera implicitement.
Dans le dialecte 1, il est possible de mélanger des données entières et des chaînes numériques, les chaînes sont implicitement converties en entiers si cela est possible, par ex :
2 + '1'
s’exécutera correctement.
Dans le dialecte 3, une telle expression provoquera une erreur, elle nécessitera une entrée de la forme suivante :
2 + CAST('1' AS SMALLINT)
Lors de la concaténation de plusieurs éléments de types différents, toutes les données qui ne sont pas des chaînes seront implicitement converties en chaînes, si possible.
SELECT 30||' days hath September, April, June and November' CONCAT$
FROM RDB$DATABASE
CONCAT$ ------------------------------------------------ 30 days hath September, April, June and November