IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ FirebirdConsultez toutes les FAQ

Nombre d'auteurs : 6, nombre de questions : 205, dernière mise à jour : 15 septembre 2014  Ajouter une question

 

Cette faq a été réalisée à partir des questions fréquement posées sur les forums Firebird de http://www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette F.A.Q. ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette F.A.Q. ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, lisez ceci

Sur ce, nous vous souhaitons une bonne lecture.
L'équipe Firebird de Developpez.com

SommaireLes requêtes (21)
précédent sommaire suivant
 

Il faut utiliser le mot clé FIRST :

Code sql : Sélectionner tout
SELECT FIRST X Champ1, Champ2 .... FROM ....
Remplacez X par le nombre voulu.

Mis à jour le 20 juin 2005 Benjamin GAGNEUX

Il faut utiliser les mots clés FIRST et SKIP :

Code sql : Sélectionner tout
SELECT FIRST X SKIP Y Champ1, Champ2 .... FROM ....
Remplacez X et Y par les nombres voulus.

Mis à jour le 20 juin 2005 Benjamin GAGNEUX

Pour cela il est nécessaire de lancer une requête sur les tables systèmes de notre base de données.

Code sql : Sélectionner tout
1
2
3
select distinct RDB$RELATION_NAME from rdb$RELATION_FIELDS 
where RDB$VIEW_CONTEXT is null 
  and RDB$SYSTEM_FLAG = 0;

Mis à jour le 4 juillet 2005 Benjamin GAGNEUX

Il y a deux variables disponibles , CURRENT_DATE qui retourne la date courante et CURRENT_TIMESTAMP qui retourne la date et l'heure. Vous pouvez les utiliser dans les instructions SQL:

Code SQL : Sélectionner tout
insert into t1 values(10, CURRENT_TIMESTAMP);
pour interroger , utilisez ceci

Code SQL : Sélectionner tout
1
2
select current_date, current_timestamp 
from rdb$database;
Vous devez faire un SELECT .. FROM quelque chose et RDB$DATABASE est la table singleton présente dans toutes les bases de données Firebird (FAQ #30).

Vous pouvez aussi utiliser ces variables en PSQL (langage des procédures stockées et triggers)

Code SQL : Sélectionner tout
1
2
3
4
5
6
7
create procedure p1 
as 
BEGIN 
if (current_timestamp > cast('2007-11-03' as timestamp)) then 
exception myerror; 
... 
END
Notez bien que CURRENT_TIMESTAMP retourne la date et heure du début de la transaction, ce qui veut dire qu'elles sont constantes durant toute celle-ci. Si vous avez besoin de la date et/ou l'heure exacte à chaque moment utilisez la valeur spéciale 'now' .

Code SQL : Sélectionner tout
1
2
select cast('now' as timestamp), cast('today' as date) 
from rdb$database
Comme vous pouvez le voir , la même règle s'applique avec CURRENT_DATE, et la valeur spéciale 'today', pour obtenir la date courante.

La raison derrière ceci est l'atomicité d'une transaction, donc CURRENT_DATE et CURRENT_TIMESTAMP doivent fournir une certaine cohérence. Spécialement pour des systèmes tournant 24H/24 7J/7 il peut très bien arriver que la date change entre le début et la fin de la transaction.
Traduction réalisée depuis http://www.firebirdfaq.org/faq114/

Mis à jour le 3 janvier 2009 SergioMaster

Quelquefois vous voulez juste savoir combien d'enregistrements fournira une requête, sans pour autant les récupérer. Avec Firebird 2 et les tables dérivées c'est facile :

Code SQL : Sélectionner tout
SELECT COUNT(*) FROM ( votre requête );
par exemple:

Code SQL : Sélectionner tout
SELECT COUNT(*) FROM ( select * from employee where emp_no > 8 );
dans les anciennes versions (1.x) de Firebird (1.x) vous devrez soit écrire la requête pour obtenir le nombre d'enregistrement, ou créer une vue puis faire un SELECT COUNT(*) sur celle-ci .
Par exemple :

Code SQL : Sélectionner tout
1
2
3
4
5
create view my_employees as select * from employee where emp_no > 8; 
commit; 
SELECT COUNT(*) FROM my_employees; 
commit; 
drop view my_employees;
Traduction réalisée depuis http://www.firebirdfaq.org/faq198/

Mis à jour le 3 janvier 2009 SergioMaster

Vous pouvez vouloir ajouter un index UNIQUE sur le champ d'une table (par exemple le champ ID) mais vous avez besoin pour cela de trouver et détruire les enregistrements en double avant. Voici une requête pour les trouver :

Code SQL : Sélectionner tout
1
2
3
4
select id, count(*) 
from t1 
group by id 
having count(*) > 1;
Traduction réalisée depuis http://www.firebirdfaq.org/faq149/

Mis à jour le 3 janvier 2009 SergioMaster

Vous pouvez utiliser la 'clé secrète' RDB$DB_KEY de Firebird. RDB$DB_KEY est un champ 'caché' qui identifie chaque ligne dans une instruction SQL. Par exemple, si vous avez une table TABLE1 sans clé primaire, avec les colonnes COL1 et COL2 qui sont les mêmes , vous pourrez effacer les lignes 'extras' ainsi :

Code SQL : Sélectionner tout
1
2
3
4
5
DELETE FROM TABLE1 t1 
WHERE EXISTS ( 
SELECT 1 FROM TABLE1 t2  
WHERE t1.COL1 = t2.COL1 and t1.COL2 = t2.COL2  
  AND t2.RDB$DB_KEY > t1.RDB$DB_KEY );
Vous pouvez contrôler quel enregistrement est considéré comme duplicata en incluant les colonnes appropriées de la table dans la clause WHERE (dans la plupart des cas vous voudrez toutes les mettre)
Traduction réalisée depuis http://www.firebirdfaq.org/faq301/

Mis à jour le 3 janvier 2009 SergioMaster

Il y a plusieurs manières de faire, par exemple, ceci fonctionne :

Code SQL : Sélectionner tout
1
2
3
4
declare variable s varchar(20); 
... 
s = 'Ceci est la ligne un. 
Ceci est la ligne deux.';
Ceci ajoutera seulement de caractère (LF) line feed sur Linux, retour Chariot (CR) sur Mac , et CRLF sur Windows. Si vous voulez un comportement unique quelle que soit la plateforme utilisez la fonction ASCII_CHAR de la bibliothèque standard IB_UDF :

Code SQL : Sélectionner tout
c = 'Ceci est la ligne un.'||ASCII_CHAR(13)||ASCII_CHAR(10)||'Ceci est la ligne deux.';
Si vous ne voulez pas utiliser les UDFs, vous pouvez toujours mettre ces caractères dans une table et les sélectionner à partir de celle-ci.
Traduction réalisée depuis http://www.firebirdfaq.org/faq132/

Mis à jour le 3 janvier 2009 SergioMaster

Supposons que vous ayez une requête d'agrégat simple , sur la base exemple employee , qui fournit le nombre d'employés pour chaque projet :

Code SQL : Sélectionner tout
1
2
3
SELECT ep.PROJ_ID, count(*) 
FROM EMPLOYEE_PROJECT ep 
GROUP BY ep.PROJ_ID;
Si vous avez besoin de plus d'informations sur le projet lui-même , vous écrirez quelque chose de ce type :

Code SQL : Sélectionner tout
1
2
3
4
SELECT ep.PROJ_ID, p.PROJ_NAME, p.PRODUCT, count(*) 
FROM EMPLOYEE_PROJECT ep 
JOIN PROJECT p on ep.PROJ_ID = p.PROJ_ID 
GROUP BY ep.PROJ_ID, p.PROJ_NAME, p.PRODUCT;
Quand vous avez un grand nombre de colonnes impliquées la liste du GROUP BY peut devenir très longue. A un certain stade , elle atteindra la limite de taille pour une clé de tri (voir FAQ #00236) soit : 64kB. Pour éviter ceci, vous pouvez utilisez MIN ou MAX pour de telles colonnes (puisque de toutes façons elles retournent des valeurs uniques):

Code SQL : Sélectionner tout
1
2
3
4
SELECT ep.PROJ_ID, MAX(p.PROJ_NAME), MAX(p.PRODUCT), count(*) 
FROM EMPLOYEE_PROJECT ep 
JOIN PROJECT p on ep.PROJ_ID = p.PROJ_ID 
GROUP BY ep.PROJ_ID
Traduction réalisée depuis http://www.firebirdfaq.org/faq304/

Mis à jour le 3 janvier 2009 SergioMaster

Une conversion directe n'est pas possible sans utiliser une UDF, mais vous pouvez extraire du texte en utilisant la fonction SUBSTRING .

Code sql : Sélectionner tout
1
2
DECLARE VARIABLE v1 VARCHAR(32000); 
SELECT SUBSTRING(nom_colonne_blob1 FROM 1 FOR 32000) FROM table1 INTO v1;
Prenez bien note que la taille maximum d'une VARCHAR est de 32767 (ce qui peut être moins selon le type de caractères utilisé, par exemple l'UTF8).

Plusieurs sous-couches d'accès aux bases de données permettent de récupérer les données BLOB en chaine, et ce directement. Par exemple, en PHP vous pouvez utiliser:

Code php : Sélectionner tout
$row = ibase_fetch_assoc($qry, IBASE_TEXT);
qui convertit automatiquement tout BLOB texte en VARCHAR, ce qui évite la nécessité d'écrire du code PHP spécifique.

Traduction réalisée depuis http://www.firebirdfaq.org/faq250/

Mis à jour le 3 janvier 2009 SergioMaster

Réponse courte : Non , pas besoin.
Réponse longue :
Firebird vous permet des identifiants en majuscules, minuscules ou les deux car il ignore la casse (case insensitive).

Code SQL : Sélectionner tout
1
2
3
SELECT * FROM Employee; 
SELECT * FROM EMPLOYEE; 
SELECT * FROM employee;
sont des instructions identiques. Firebird stockes les identifiants sans préserver la casse utilisée (lire plus bas), ainsi si vous utilisez un outil d'administration qui extrait ses informations des tables systèmes , vous obtiendrez tous les noms en majuscules.

Si vous voulez vraiment utiliser des minuscules (et non seulement des majuscules) vous devrez mettre des doubles apostrophes pour chaque identifiant. Attention, une fois fait, vous devrez tout le temps le faire.

Code SQL : Sélectionner tout
1
2
3
SELECT * FROM "Employee"; 
SELECT * FROM "EMPLOYEE"; 
SELECT * FROM "employee";
sont trois instructions différentes. Quand vous utilisez les guillemets, Firebird stocke le nom tel qu'il a été écrit .
Vous pouvez aussi utiliser les guillemets pour stocker des caractères autrement illégaux tels que point, virgule, double point , point d'interrogation et caractères nationaux (non ASCII), ou un mot clé SQL réservé (par exemple pour avoir une colonne nommée User ou Date ).
Certains utilisateurs préfèrent ne pas compliquer les choses et n'utilisent aucune apostrophe , d'autres adorent avoir une casse mélangée et ne sont pas gênés par les doubles apostrophes. La plupart des outils d'administration (FlameRobin inclus) ont une option de configuration pour répondre a vos besoins : apostrophes seulement si besoin , ou apostrophes tout le temps.
Traduction réalisée depuis http://www.firebirdfaq.org/faq76/

Mis à jour le 3 janvier 2009 SergioMaster

Si vous essayez d'écrire une expression telle que char + char ou varchar + varchar, ou si vous essayez d'ajouter une valeur chaine à une autre , vous obtiendrez un message d'erreur comme celui-ci :

expression evaluation not supported

La raison, le + n'est pas l'opérateur de concaténation de chaine en SQL standard , c'est ||.

Code SQL : Sélectionner tout
select first_name||' '||last_name from employee;
Notez que, si une des colonnes est nulle, le résultat sera NULL. Pourquoi? Eh bien parce que, NULL veux dire que la valeur est inconnue , ce qui fait que si vous mettez ensemble une valeur connue et une inconnue vous ne pouvez pas savoir ce que vous allez obtenir comme résultat. C'est pourquoi le résultat est aussi inconnu soit : NULL.

Pour contourner ce problème, utilisez la fonction COALESCE.

Prenez également en compte que, contrairement à certains autres systèmes de bases de données, Firebird suit les normes SQL, et que NULL n'est pas la même chose qu'une chaîne vide ''.
Traduction réalisée depuis http://www.firebirdfaq.org/faq21/

Mis à jour le 3 janvier 2009 SergioMaster

Vous pouvez avoir un problème de ce genre :

Code sql : Sélectionner tout
1
2
3
4
5
CREATE TABLE t1 ( c1 CHAR(5) ); 
COMMIT; 
  
INSERT INTO t1 VALUES ('abcd'); 
SELECT * FROM t1 WHERE c1 LIKE '%cd';
Le SELECT ci-dessus ne retournera rien. La raison en est que les colonnes de type CHAR sont toujours remplies à droite avec des espaces à concurrence de la longueur définie, donc la colonne contient 'abcd ', avec un espace à la fin. Jetez un oeil à la FAQ #00237 pour plus de détails.

Pour contourner ceci vous utiliserez un VARCHAR, ou retaillerez la colonne en utilisant les fonctions TRIM ou RTRIM

Code sql : Sélectionner tout
SELECT * FROM t1 WHERE RTRIM(c1) LIKE '%cd';
RTRIM fait partie de la bibliothèque IB_UDF. Si vous ne l'avez pas déclaré référez-vous à la FAQ #00169 pour apprendre à l'activer.
Traduction réalisée depuis http://www.firebirdfaq.org/faq309/

Mis à jour le 3 janvier 2009 SergioMaster

C'est ainsi conceptualisé. CURRENT_TIMESTAMP fournit la même valeur pour tout un ensemble d'instructions. Cela veut dire que CURRENT_TIMESTAMP aura la même valeur à l'intérieur d'un ensemble, et également durant l'exécution d'une procédure stockée et des différentes procédures pouvant être appelées par celle-ci .

Si vous voulez obtenir la 'vraie' heure plutôt que l'heure de l'exécution utilisez 'now' qui est une valeur spéciale.

Code sql : Sélectionner tout
1
2
select cast('now' as timestamp) 
from ...
'now' étant une chaîne , elle est évaluée (convertie en horodate) à chaque exécution.
Traduction réalisée depuis http://www.firebirdfaq.org/faq56/

Mis à jour le 3 janvier 2009 SergioMaster

Vous pouvez transformer le résultat dans le set de caractères OCTETS. C'est utilisé pour mettre en clair des données binaires et la plupart des clients (ISQL, FlameRobin, etc.) l'affichera en hexadécimal. Exemple:

Code sql : Sélectionner tout
1
2
SELECT CAST('Firebird' AS VARCHAR(20) CHARACTER SET OCTETS) 
FROM RDB$DATABASE
Affichera

Code sql : Sélectionner tout
4669726562697264
Traduction réalisée depuis http://www.firebirdfaq.org/faq339/

Mis à jour le 3 janvier 2009 SergioMaster

Oui. Vous aurez besoin d'utiliser une double paire de parenthèses. Exemple:

Code sql : Sélectionner tout
1
2
ALTER TABLE t1 ADD compteur_relation  
COMPUTED BY ( (SELECT COUNT(*) FROM RDB$RELATIONS) );
Prenez bien note que les expressions COMPUTED BY qui se réfèrent à d'autres tables n'auront pas de bonnes performances car un nouveau SELECT est exécuté pour chaque ligne. Il est bien mieux de créer une vue, une procédure stockée - ou d'utiliser un EXECUTE BLOCK si vous voulez le faire en une seule fois.
Traduction réalisée depuis http://www.firebirdfaq.org/faq289/

Mis à jour le 3 janvier 2009 SergioMaster

La manière la plus courante en SQL est la suivante:

Code sql : Sélectionner tout
1
2
3
4
5
6
UPDATE dest_table t1 
SET  
field1 = (select field1 from src_table t2 where t2.pk = t1.pk), 
field2 = (select field2 from src_table t2 where t2.pk = t1.pk), 
...etc. 
WHERE EXISTS (select 1 from src_table t2 where t2.pk = t1.pk)
Avec Firebird 2, vous pouvez utiliser un EXECUTE BLOCK pour écrire une expression plus efficace :

Code sql : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
EXECUTE BLOCK 
AS 
DECLARE VARIABLE field1 type; 
DECLARE VARIABLE field2 type; 
...etc. 
DECLARE VARIABLE pk type; 
BEGIN 
for select pk, field1, field2, ... from src_table 
into :pk, :field1, :field2, ... 
do update dest_table set field1 = :field1, field2 = :field2, ... 
where pk = :pk; 
END
Avec Firebird 1.x, vous pourrez écrire une procédure pour faire le travail.

Outre le SQL direct, vous pouvez utiliser des outils tels que FBExport qui vous permettra une meilleure manipulation des erreurs (il sera plus facile de trouver la ligne exacte ainsi que la colonne qui empêche la mise à jour). Voici un exemple avec FBExport, premièrement exporter les données vers un fichier:

Code text : Sélectionner tout
fbexport -S -Q "select pk, field1, field2, ... from src_table" -F test.fbx


Ensuite les importer dans une autre table :

Code text : Sélectionner tout
fbexport -If -Q "update dest_table set field1 = :2, field2 = :3, ... where pk = :1" -F test.fbx

FBExport est un outil open source. Le téléchargement de la dernière version est ici
Traduction réalisée depuis http://www.firebirdfaq.org/faq323/

Mis à jour le 3 janvier 2009 SergioMaster

Vous pourriez avoir une procédure stockée qui fait quelque chose avec une table, mais dont le nom de cette table ne soit connu qu'à l'exécution. Vous pouvez faire cela avec un EXECUTE STATEMENT. Par exemple , nous voulons fournir le nom de la table dont nous voulons extraire le champ ID :

Code sql : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
SET TERM !! ; 
  
CREATE PROCEDURE p1 ( TableName VARCHAR(32)) 
RETURNS ( id integer ) 
AS 
DECLARE VARIABLE stmt VARCHAR(1000); 
BEGIN 
stmt = 'select id from '||:TableName; 
for execute statement :stmt into :id 
do suspend; 
END; 
  
SET TERM ; !!
Vous pouvez faire pareil avec des vues ou des procédures. La seule chose qui ne peut être variable c'est le nombre et nom des paramètres de sortie .
Traduction réalisée depuis http://www.firebirdfaq.org/faq322/

Mis à jour le 3 janvier 2009 SergioMaster

Une conversion directe n'est pas possible sans utiliser une UDF, mais vous pouvez extraire du texte en utilisant la fonction SUBSTRING .

Code sql : Sélectionner tout
1
2
DECLARE VARIABLE v1 VARCHAR(32000); 
SELECT SUBSTRING(nom_colonne_blob1 FROM 1 FOR 32000) FROM table1 INTO v1;
Prenez bien note que la taille maximum d'une VARCHAR est de 32767 (ce qui peut être moins selon le type de caractères utilisé, par exemple l'UTF8).

Plusieurs sous-couches d'accès aux bases de données permettent de récupérer les données BLOB en chaine, et ce directement. Par exemple, en PHP vous pouvez utiliser:

Code php : Sélectionner tout
$row = ibase_fetch_assoc($qry, IBASE_TEXT);
qui convertit automatiquement tout BLOB texte en VARCHAR, ce qui évite la nécessité d'écrire du code PHP spécifique.

Traduction réalisée depuis http://www.firebirdfaq.org/faq250/

Mis à jour le 3 janvier 2009 SergioMaster

Parfois vous devez fournir une requête SQL à un outil tiers ou à un composant, en souhaitant qu'elle renvoie le numéro de chaque ligne. Bien que cela soit facilement faisable via une variable temporaire dans une procédure stockée ou en utilisant un EXECUTE BLOCK, vous pouvez souhaiter cette numérotation au titre d'un simple SELECT .

Les variables de contexte de Firebird peuvent faire le travail pour vous . Voici une manière de faire proposée par Fabiano Bonin. Cet exemple montre toutes les tables et vues de la base de données :

Exemple pour les bases de données en Dialect 3 :

Code sql : Sélectionner tout
1
2
3
4
5
6
7
SELECT 
rdb$get_context('USER_TRANSACTION', 'row#') as row_number, 
rdb$set_context('USER_TRANSACTION', 'row#', 
COALESCE(cast(rdb$get_context('USER_TRANSACTION', 'row#') as integer), 0) + 1), 
a.rdb$relation_name 
FROM rdb$relations a 
ORDER BY a.rdb$relation_name
Exemple pour les bases de données en Dialect 1 :

Code sql : Sélectionner tout
1
2
3
4
5
6
7
SELECT 
rdb$get_context('USER_TRANSACTION', 'row#') as row_number, 
rdb$set_context('USER_TRANSACTION', 'row#', 
COALESCE(rdb$get_context('USER_TRANSACTION','row#'),0) + 1), 
a.rdb$relation_name 
FROM rdb$relations a 
ORDER BY a.rdb$relation_name
l'exemple pour le Dialect 1 est une contribution de Serge Girard du site developpez.net.

Traduction réalisée depuis http://www.firebirdfaq.org/faq343/

Mis à jour le 10 mars 2009 SergioMaster

La plus importante est que CHAR est rempli avec des espaces à droite alors que VARCHAR ne l'est pas. Par exemple, avec ceci :

Code sql : Sélectionner tout
1
2
3
4
5
CREATE TABLE t1 ( 
v1 VARCHAR(4), 
c2 CHAR(4) 
); 
INSERT INTO t1 (v1,c2) VALUES ('a', 'a');
La colonne v1 contiendra la valeur 'a', tandis que la colonne c2 contiendra 'a ' avec les espaces additionnels. Les espaces de fin seront ignorés lors des comparaisons, ce qui fait que les deux clauses WHERE suivantes fonctionneront :

Code sql : Sélectionner tout
1
2
.. WHERE v1 = 'a' 
..WHERE c2 = 'a'
Les espaces de fin, par contre, sont respectés par l'opérateur LIKE, ce qui peut être source de confusion chez le débutant.
Traduction réalisée depuis http://www.firebirdfaq.org/faq237/

Mis à jour le 1er mai 2009 SergioMaster

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2021 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.