IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Les requêtes
        Comment récupérer les X premiers enregistrements ?
        Comment récupérer les X enregistrements après l'enregistrement Y ?
        Comment récupérer le nom des tables d'une base de données ?
        Comment obtenir la date et l'heure du serveur Firebird ?
        Comment obtenir le nombre d'enregistrements d'une requête sans l'exécuter ?
        Comment trouver les enregistrements en double ?
        Comment effacer des enregistrements en double (quand la table n'a pas de clé primaire) ?
        Comment intégrer un saut de ligne (CRLF) à une chaine en SQL?
        Comment éviter d'avoir des listes GROUP BY importantes quand on fait la jonction de plusieurs tables ?
        Comment convertir un BLOB en string?
        Dois-je mettre les identifiants en majuscules ?
        Pourquoi chaine + chaine ne fonctionne pas ?
        Pourquoi LIKE ne fonctionne pas avec le caractère de remplacement % au début?
        Pourquoi CURRENT_TIMESTAMP renvoie la même valeur pour toutes les lignes?
        Y a t-il une fonction comme DUMP en Oracle?
        Est-il possible d'utiliser un SELECT pour calculer des colonnes COMPUTED ?
        Comment mettre à jour des colonnes d'une table en utilisant les valeurs d'une autre table ?
        Comment fournir le nom d'une vue, procédure ou table à une procédure stockée ?
        Comment convertir un BLOB en string?
        Comment avoir le numéro d'enregistrement à l'intérieur d'un ensemble de données ?
        Quelle est la différence entre CHAR et VARCHAR?



Comment récupérer les X premiers enregistrements ?
auteur : Benjamin GAGNEUX
Il faut utiliser le mot clé FIRST :

SELECT FIRST X Champ1, Champ2 .... FROM ....
Remplacez X par le nombre voulu.

lien : faq Comment récupérer les X enregistrements après l'enregistrement Y ?

Comment récupérer les X enregistrements après l'enregistrement Y ?
auteur : Benjamin GAGNEUX
Il faut utiliser les mots clés FIRST et SKIP :

SELECT FIRST X SKIP Y Champ1, Champ2 .... FROM ....
Remplacez X et Y par les nombres voulus.

lien : faq Comment récupérer les X premiers enregistrements ?

Comment récupérer le nom des tables d'une base de données ?
auteur : Benjamin GAGNEUX
Pour cela il est nécessaire de lancer une requête sur les tables systèmes de notre base de données.

select distinct RDB$RELATION_NAME from rdb$RELATION_FIELDS
where RDB$VIEW_CONTEXT is null
  and RDB$SYSTEM_FLAG = 0;

Comment obtenir la date et l'heure du serveur Firebird ?
auteur : SergioMaster
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:

insert into t1 values(10, CURRENT_TIMESTAMP);
pour interroger , utilisez ceci

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)


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

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/


Comment obtenir le nombre d'enregistrements d'une requête sans l'exécuter ?
auteur : 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 :

SELECT COUNT(*) FROM ( votre requête );
par exemple:

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 :

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/


Comment trouver les enregistrements en double ?
auteur : 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 :

select id, count(*)
from t1
group by id
having count(*) > 1;
Traduction réalisée depuis http://www.firebirdfaq.org/faq149/

lien : faq Comment effacer des enregistrements en double (quand la table n'a pas de clé primaire) ?

Comment effacer des enregistrements en double (quand la table n'a pas de clé primaire) ?
auteur : 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 :

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/


Comment intégrer un saut de ligne (CRLF) à une chaine en SQL?
auteur : SergioMaster
Il y a plusieurs manières de faire, par exemple, ceci fonctionne :

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 :

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/


Comment éviter d'avoir des listes GROUP BY importantes quand on fait la jonction de plusieurs tables ?
auteur : 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 :

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 :

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

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/


Comment convertir un BLOB en string?
auteur : SergioMaster
Une conversion directe n'est pas possible sans utiliser une UDF, mais vous pouvez extraire du texte en utilisant la fonction SUBSTRING .

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:

$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/


Dois-je mettre les identifiants en majuscules ?
auteur : 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).

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.

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/


Pourquoi chaine + chaine ne fonctionne pas ?
auteur : 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 ||.

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/


Pourquoi LIKE ne fonctionne pas avec le caractère de remplacement % au début?
auteur : SergioMaster
Vous pouvez avoir un problème de ce genre :

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

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/


Pourquoi CURRENT_TIMESTAMP renvoie la même valeur pour toutes les lignes?
auteur : 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.

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/


Y a t-il une fonction comme DUMP en Oracle?
auteur : 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:

SELECT CAST('Firebird' AS VARCHAR(20) CHARACTER SET OCTETS)
FROM RDB$DATABASE
Affichera

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


Est-il possible d'utiliser un SELECT pour calculer des colonnes COMPUTED ?
auteur : SergioMaster
Oui. Vous aurez besoin d'utiliser une double paire de parenthèses. Exemple:

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/


Comment mettre à jour des colonnes d'une table en utilisant les valeurs d'une autre table ?
auteur : SergioMaster
La manière la plus courante en SQL est la suivante:

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 :

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:


fbexport -S -Q "select pk, field1, field2, ... from src_table" -F test.fbx


Ensuite les importer dans une autre table :

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/


Comment fournir le nom d'une vue, procédure ou table à une procédure stockée ?
auteur : 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 :

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/


Comment avoir le numéro d'enregistrement à l'intérieur d'un ensemble de données ?
auteur : 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 :

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 :

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/


Quelle est la différence entre CHAR et VARCHAR?
auteur : SergioMaster
La plus importante est que CHAR est rempli avec des espaces à droite alors que VARCHAR ne l'est pas. Par exemple, avec ceci :

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 :

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

lien : faq Pourquoi LIKE ne fonctionne pas avec le caractère de remplacement % au début?


Consultez les autres F.A.Q's


Valid XHTML 1.1!Valid CSS!

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 © 2009 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.