FirebirdSQL logo

DECIMAL

Format déclarative des données
  DECIMAL
| DECIMAL(precision)
| DECIMAL(precision, scale)
Table 1. Paramètres de type DECIMAL
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)

Précision des opérations arithmétiques

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).

Types de données pour travailler avec la date et l’heure

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 DATE peut être déclaré comme TIMESTAMP.Cette déclaration est recommandée pour les nouvelles bases de données en dialecte 1.

Fractions de seconde

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 TIME ou TIMESTAMP est un entier de 4 octets (WORD) contenant une valeur de temps avec des fractions de seconde, et stockée comme le nombre de dix millièmes de seconde écoulés depuis minuit.La précision réelle des valeurs obtenues à partir des fonctions et des variables de l’horodateur sera la suivante :

  • CURRENT_TIME — est précis à la seconde par défaut, la précision en millisecondes peut être spécifiée comme suit : CURRENT_TIME (0 | 1 | 2 | 3).

  • CURRENT_TIMESTAMP — est précise à la milliseconde près par défaut, une précision de la seconde à la milliseconde peut être spécifiée comme suitCOURANT_TIMESTAMP (0 | 1 | 2 | 3)

  • LOCALTIME — est précis à la seconde par défaut, la précision en millisecondes peut être spécifiée comme suitLOCALTIME (0 | 1 | 2 | 3)

  • LOCALTIMESTAMP — est précis à la milliseconde près par défaut, une précision de la seconde à la milliseconde peut être spécifiée comme suitLOCALTIMESTAMP (0 | 1 | 2 | 3)

  • Le littéral 'NOW' est précis en millisecondes ;

  • Les fonctions DATEADD et DATEDIFF supportent une précision au dixième de milliseconde.

  • La fonction EXTRACT renvoie des valeurs précises au dixième de milliseconde pour les arguments SECOND et MILLISECOND ;

Stockage des types de fuseaux horaires

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 '00:00:00.0000'.

Example 1. Exemple d’utilisation DATE
CRETE TABLE DataLog(
  id BIGINT NOT NULL,
  bydate DATE
);
...
AS
  DECLARE BYDATE DATE;
BEGIN
...

TIME

Syntaxe
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 EXTENDED TIME WITH TIME ZONE est uniquement utilisée lors de la communication avec les clients, elle résout le problème de la présentation de l’heure correcte sur les clients qui n’ont pas de bibliothèque ICU.Vous ne pouvez pas utiliser les Types de données étendus dans les tables, les procédures, etc.La seule façon d’utiliser ces types de données est de procéder à un casting des types de données, y compris l’instruction SET BIND

(pour plus d’informations, voir la rubrique SET BIND OF).

Example 1. Exemple d’utilisation de 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
...

TIMESTAMP

Syntaxe
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

EXTENDED TIMESTAMP WITH TIME ZONE est uniquement destiné à être utilisé lors de la communication avec les clients, il résout le problème de la présentation de l’heure correcte sur les clients qui ne disposent pas d’une bibliothèque ICU.Vous ne pouvez pas utiliser les Types de données étendus dans les tables, les procédures, etc.La seule façon d’utiliser ces types de données est de procéder à un casting des types de données, y compris l’instruction SET BIND

(pour plus d’informations, voir la rubrique SET BIND OF).

Example 1. Exemple d’utilisation de TIME
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
...

Fuseau horaire de la session

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 ZONEou rétablissez la valeur d’origine avec `SET TIME ZONE LOCAL'.

Obtention d’un fuseau horaire de session

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.

Example 1. Obtention d’un fuseau horaire de session
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

Format du fuseau horaire

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.

Sémantique régionale TIME WITH TIME ZONE

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.

Litérals de date et d’heure

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.

Syntaxe
<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 | . | : | , | - | /
Table 1. Description du format de la date et de l’heure
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.

Example 1. Exemples de littéraux de date et d’heure
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.

Opérations utilisant les valeurs de date et d’heure

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.

Table 1. Opérations arithmétiques pour les types de données date et heure
Opérande 1 Opérateur Opérande 2 Résultat

DATE

+

TIME

TIMESTAMP

DATE

+

TIME WITH TIME ZONE

TIMESTAMP WITH TIME ZONE

DATE

+

Valeur numérique n

DATE, augmenté de n jours entiers (la partie fractionnaire est ignorée).

TIME

+

DATE

TIMESTAMP

TIME WITH TIME ZONE

+

DATE

TIMESTAMP WITH TIME ZONE

TIME

+

Valeur numérique n

TIME, augmenté de n secondes (nombre de parties fractionnaires).

TIME WITH TIME ZONE

+

Valeur numérique n

TIME WITH TIME ZONE, augmenté de n secondes (nombre de parties fractionnaires).

TIMESTAMP

+

Valeur numérique n

TIMESTAMP, où la date sera augmentée du nombre de jours et de la partie du jour représentée par le nombre n - donc “+ 2.75” avancera la date de 2 jours et 18 heures.

TIMESTAMP WITH TIME ZONE

+

Valeur numérique n

TIMESTAMP WITH TIME ZONE, où la date sera augmentée du nombre de jours et de la partie du jour représentée par le nombre n - donc “+ 2.75” avancera la date de 2 jours et 18 heures.

DATE

-

DATE

Nombre de jours dans l’intervalle comme DECIMAL (9, 0).

DATE

-

Valeur numérique n

DATE, réduit de n jours entiers (la partie fractionnaire est ignorée).

TIME

-

TIME

Le nombre de secondes dans l’intervalle comme DECIMAL (9, 4).

TIME

-

n

TIME, réduit de n secondes (nombre de parties fractionnaires).

TIME

-

TIME WITH TIME ZONE

La valeur sans fuseau horaire est convertie en WITH TIME ZONE dans le fuseau horaire de la session en cours.Le nombre de secondes entre les valeurs UTC est renvoyé comme suit DECIMAL(9, 4).La même règle s’applique lorsque l’ordre des opérandes est modifié.

TIME WITH TIME ZONE

-

TIME WITH TIME ZONE

Le nombre de secondes entre les valeurs UTC est renvoyé comme suit DECIMAL(9, 4).

TIMESTAMP

-

TIMESTAMP

Nombre de jours et de parties d’un jour dans un intervalle comme DECIMAL (18, 9).

TIMESTAMP

-

TIMESTAMP WITH TIME ZONE

La valeur sans fuseau horaire est convertie en WITH TIME ZONE dans le fuseau horaire de la session en cours.Le nombre de jours et de parties de la journée entre les valeurs UTC en tant que DECIMAL (18, 9).La même règle s’applique lorsque l’ordre des opérandes est modifié.

TIMESTAMP

-

n

TIMESTAMP, où la date sera réduite par le nombre de jours, et la partie du jour représentée par le nombre n - ainsi “`- 2.25`” reculera la date de 2 jours et 6 heures.

TIMESTAMP WITH TIME ZONE

-

n

TIMESTAMP WITH TIME ZONE, où la date sera réduite par le nombre de jours, et la partie du jour représentée par le nombre n - ainsi “`- 2.25`” reculera la date de 2 jours et 6 heures.

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 DATE est traité comme TIMESTAMP.

Fonctions supplémentaires pour le support des fuseaux horaires

Firebird 4 offre un certain nombre de fonctionnalités pour les informations sur les fuseaux horaires.

Table virtuelle 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".

Paquet 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.

Mise à jour de la base de données des fuseaux horaires

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

/tzdata — est le répertoire par défaut dans lequel Firebird recherche la base de données des fuseaux horaires.Il peut être surchargé en utilisant la variable d’environnement ICU_TIMEZONE_FILES_DIR.

Symbole Types de données

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'.

Unicode

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.

Syntaxe
{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.

Jeu de caractères du client

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.

Jeux de caractères spéciaux

Jeu de caractères `NONE'.

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.

Jeu de caractères `OCTETS

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é.

Séquence de tri

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.

Recherche indépendante de la casse

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
Voir aussi:

CONTAINING.

Séquences de tri pour UTF-8

Vous trouverez ci-dessous un tableau des séquences de tri possibles pour le jeu de caractères UTF8.

Table 1. Séquences de tri pour 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

Indexation des types de caractères

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),

N — nombre d’octets par représentation de caractère.

Table 1. Longueur de la chaîne indexée et jeu de caractères

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.

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.

Syntaxe
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].

Voir aussi:

CHAR, CHARACTER SET OCTETS.

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.

Syntaxe
{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.

Syntaxe
{VARBINARY  | BINARY VARYING} (<length>)
Note

Ce type est un alias du type `VARCHAR (<length>) CHARACTER SET OCTETS' et est rétrocompatible avec celui-ci.

Example 1. Utilisation des types BINARY et VARBINARY dans PSQL
DECLARE VARIABLE VAR1 VARBINARY(10);
Example 2. Utilisation des types BINARY et VARBINARY lors de la définition d’une table
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.

Syntaxe
 {VARCHAR | {CHAR | CHARACTER} VARYING} (length)
  [CHARACTER SET <charset>] [COLLATE <collate>]

Type de données logiques

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.

Opérateur 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
  • Les opérateurs d’équivalence (“`=`”, “!=”, “<>`” etc.) sont autorisés dans toutes les comparaisons.

Exemples BOOLEAN

INSERT et SELECT
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>
Vérification de la valeur "TRUE".
SELECT * FROM TBOOL WHERE BVAL
ID           BVAL
============ =======
1            <true>
Vérification de la valeur FALSE.
SELECT * FROM TBOOL WHERE BVAL IS FALSE
ID           BVAL
============ =======
2            <false>
Vérification de la valeur UNKNOWN.
SELECT * FROM TBOOL WHERE BVAL IS UNKNOWN
ID           BVAL
============ =======
3            <null>
Expressions logiques dans une liste SELECT
SELECT ID, BVAL, BVAL AND ID < 2
FROM TBOOL
ID           BVAL
============ ======= =======
1            <true> <true>
2            <false> <false>
3            <null> <false>
PSQL annonces avec valeur assigné
DECLARE VARIABLE VAR1 BOOLEAN = TRUE;
Comparaisons avec UNKNOWN
-- 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

Utilisation de booléens avec d’autres types de données

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
  • Le type de données BOOLEAN est représenté dans l’API par le type FB_BOOLEAN et les constantes FB_TRUE et FB_FALSE.

  • La valeur de TRUE est supérieure à la valeur de FALSE.

Types de données Binaire

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.

Syntaxe
BLOB [SUB_TYPE <subtype>]
  [SEGMENT SIZE <seg_length>]
  [CHARACTER SET <charset>]
  [COLLATE <collation name>]
Syntaxe abrégée :
BLOB (<seg_length>)
BLOB (<seg_length>, <subtype>)
BLOB (, <subtype>)
Taille du segment :

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.

Sous-types BLOB

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 :

Sous-type 0 (BINAIRE)

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.)

Sous-type 1 (TEXTE)

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.

Sous-types personnalisés

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.

Caractéristiques des BLOB

Taille

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.

Opérateurs et expressions

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)

BETWEEN,

IS [NOT] DISTINCT FROM,

IN,

ANY | SOME,

ALL

 

Les opérateurs suivants sont partiellement pris en charge :

  • Une erreur se produit si le second argument est supérieur ou égal à 32Kb.

    STARTING [WITH],

    LIKE,

    CONTAINING

     

  • 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 :

    SELECT DISTINCT

    produit par erreur des valeurs NULL multiples si elles sont présentes

    ORDER BY

     — 

    GROUP BY

    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

Stockage BLOB
  • 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.

Voir aussi:

FILTER, DECLARE FILTER.

Tableaux

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.

Spécifier des limites explicites pour les mesures

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

Ajout de mesures supplémentaires

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]);

Utilisation des tableaux

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.

Types de données Spécial

Type de données 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 :

Paramètres définis par l’utilisateur
  • 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).

L’utilisateur a laissé le champ vide
  • 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.

Conversion des types de données

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.

Conversion explicite des types de données

Lorsqu’une conversion explicite d’un type à un autre est nécessaire, la fonction CAST est utilisée.

Syntaxe
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

Conversion en domaine

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.

Conversion en type de colonne

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;

Transformations permises pour la fonction CAST

Table 1. Transformations permises pour la fonction CAST
Type d’origine Cast

Type numérique

Type numérique, [VAR]CHAR, BLOB

[VAR]CHAR, BLOB

[VAR]CHAR, BLOB, BOOLEAN, Types numériques, DATE, TIME, TIMESTAMP

DATE, TIME

[VAR]CHAR, BLOB, TIMESTAMP

TIMESTAMP

[VAR]CHAR, BLOB, TIME, DATE

BOOLEAN

[VAR]CHAR, BLOB

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 TIMESTAMP en DATE.

Conversion de chaînes de caractères en date et heure

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;
Table 1. Description du format de la date et de l’heure
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

Table 2. Linéaires prédéfinis de date et d’heure
Les littéraux Valeur Type de données pour le dialecte 1 Type de données pour le dialecte 3

'NOW'

Date et heure actuelles

TIMESTAMP

TIMESTAMP

'TODAY'

Date actuelle

TIMESTAMP (avec un temps nul)

DATE (date uniquement)

'TOMORROW'

Date de demain

TIMESTAMP (avec un temps nul)

DATE (date uniquement)

'YESTERDAY'

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.

Example 1. Convertir des chaînes de caractères en date et heure :
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) renvoie toujours les valeurs réelles de la date et de l’heure, il peut être utilisé pour mesurer les intervalles de temps et la vitesse d’exécution du code dans les procédures PSQL, les déclencheurs et les blocs de code.

Example 2. Utilisation de CAST('NOW' AS TIMESTAMP) pour mesurer la durée d’exécution du code
EXECUTE 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

Conversion implicite des types de données

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)

Conversion de type implicite pendant la concaténation

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.

Example 1. Conversion de type implicite pendant la concaténation
SELECT 30||' days hath September, April, June and November' CONCAT$
FROM RDB$DATABASE
CONCAT$
------------------------------------------------
30 days hath September, April, June and November