FirebirdSQL logo
 Structure du langage SQLÉléments communs du langage 

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