Aller au contenu
Base de données · 1 / 5

Le fichier physique (PF), des DDS au SQL

Le PF est la table de l'IBM i. On le crée encore souvent en DDS, un langage en colonnes né avec le System/38 en 1978. Pourquoi les DDS ont été inventées, comment créer un PF, y ajouter, modifier et supprimer des données avec UPDDTA, puis la même table en SQL et ce qui change vraiment, démontré sur un IBM i 7.5.

1978les DDS naissent avec le System/38
1format d'enregistrement par PF
F23deux fois pour supprimer dans UPDDTA
CPF5029SQL refuse une donnée invalide, le PF DDS l'accepte

En une phrase

Un fichier physique (PF, physical file) est l'objet *FILE qui contient les données d'une table : un format d'enregistrement qui décrit ses zones, les enregistrements eux-mêmes, et souvent une clé. On le décrit en DDS ou on le crée en SQL : dans les deux cas, c'est le même type d'objet, lisible par un programme RPG comme par une requête SQL.

Pourquoi les DDS ont été inventées

En 1978, IBM présente le System/38, ancêtre direct de l'AS/400, avec une base de données intégrée au système. Dans le recueil technique qu'IBM publie la même année, C. D. Truxal et S. R. Ridenour décrivent le problème qu'il fallait régler : jusque-là, chaque programme, chaque utilitaire décrivait lui-même les données qu'il lisait, et ces descriptions différaient souvent. Résultat : des définitions en double, et des programmes incompatibles entre eux.

Avant et après les DDS Avant : chaque programme décrit lui-même l'enregistrement du fichier, avec des descriptions qui peuvent différer. Avec le System/38 : une seule description DDS, rangée avec le fichier, que les compilateurs, les utilitaires et les commandes réutilisent. Avant : description dans chaque programme System/38 : une description centrale Programme Adécrit CLIENT à sa façon Programme Bautre description de CLIENT Utilitaireencore une autre Fichier CLIENTune suite d'octets Source DDSzones, types, textes CRTPF PF CLIENTdonnées + description Compilateurs, utilitairesrelisent la description
D'après Truxal et Ridenour, « File and data definition facilities in System/38 », IBM, 1978.

La réponse du System/38 : une seule description, au niveau de la zone, rangée avec le fichier pour toute sa vie. Les compilateurs la relisent (le programme RPG n'a plus à décrire l'enregistrement : c'est le fichier décrit en externe), les utilitaires s'en servent pour afficher des invites claires, et chaque format porte un niveau : si la description change, un programme compilé avec l'ancienne est signalé. Les fichiers décrits dans le programme restent possibles, surtout pour convertir les applications existantes.

Pourquoi un langage en colonnes ? Dans le même recueil, A. J. Conway et D. G. Harvey expliquent que décrire des fichiers, des zones, des écrans est un travail déclaratif, traditionnellement fait sur des formulaires à colonnes fixes. Plutôt que de l'enfermer dans le CL, langage de commandes, ou dans le RPG, IBM crée un formulaire séparé, à l'image du RPG III de l'époque : la data description specification, les DDS. Elle sert aux fichiers base de données comme aux écrans et aux états imprimés.

Sur l'AS/400, le SQL est proposé par un programme sous licence, SQL/400 (5728-ST1), dont le guide de programmation porte un copyright de 1988. Depuis, les deux façons coexistent et produisent le même type d'objet.

Ce qu'est un PF

  • Un objet de type *FILE, d'attribut PF, rangé dans une bibliothèque, qui contient les données. Le fichier logique (LF), lui, n'en contient pas : c'est une vue, un autre ordre ou une sélection sur un ou plusieurs PF.
  • Un seul format d'enregistrement : la liste des zones, avec leur type et leur longueur.
  • Des membres : les enregistrements sont rangés dans un ou plusieurs membres. Le recueil de 1978 cite l'exemple d'un fichier de commandes annuel à douze membres, un par mois. Par défaut, CRTPF n'en permet qu'un (MAXMBRS(1)).
  • Un chemin d'accès : par ordre d'arrivée, ou par clé si le PF en déclare une.
  • Les fichiers source (QDDSSRC, QRPGLESRC…) sont eux aussi des PF : chaque membre est un source.

Créer un PF en DDS

Sur notre IBM i 7.5, une bibliothèque JOBIPF et un fichier source pour les DDS :

CRTLIB    LIB(JOBIPF) TEXT('job-i.fr : demonstration PF')
CRTSRCPF  FILE(JOBIPF/QDDSSRC) RCDLEN(92)

Le membre CLIENT, de type PF, saisi par exemple avec SEU (STRSEU) ou dans VS Code avec Code for IBM i :

     A* Fichier des clients : un format, une cle unique
     A                                      UNIQUE
     A          R CLIENTR                   TEXT('Client')
     A            NUMCLI         5P 0       COLHDG('Numero' 'client')
     A                                      TEXT('Numero du client')
     A            NOM           30A         COLHDG('Nom')
     A                                      TEXT('Raison sociale')
     A            VILLE         20A         COLHDG('Ville')
     A            CATEG          1A         COLHDG('Cat')
     A                                      TEXT('Categorie A, B ou C')
     A                                      VALUES('A' 'B' 'C')
     A            SOLDE          9P 2       COLHDG('Solde')
     A                                      EDTCDE(J)
     A          K NUMCLI

Chaque information a sa colonne :

ColonnesContenu
6Type de spécification : A pour les fichiers base de données (facultatif).
7Un astérisque fait de la ligne un commentaire.
17Type de ligne : R pour le format d'enregistrement, K pour une zone clé, blanc pour une zone.
19 à 28Nom du format, de la zone ou de la clé (10 caractères au plus).
30 à 34Longueur de la zone.
35Type de données : A caractère, P décimal condensé (packed), S décimal étendu (zoned), B binaire, L date, T heure, Z horodatage…
36 et 37Nombre de décimales d'une zone numérique.
45 à 80Mots-clés : TEXT, COLHDG, VALUES, EDTCDE, et au niveau du fichier UNIQUE.

Ici : UNIQUE interdit deux clients de même numéro, R CLIENTR nomme le format, 5P 0 déclare un décimal condensé de 5 chiffres sans décimale, COLHDG donne l'en-tête de colonne que reprennent les utilitaires, VALUES limite la catégorie à A, B ou C, et K NUMCLI fait de NUMCLI la clé. Puis on compile :

CRTPF  FILE(JOBIPF/CLIENT) SRCFILE(JOBIPF/QDDSSRC)
CPC7301  Fichier CLIENT créé dans la bibliothèque JOBIPF.
CPC7305  Membre CLIENT ajouté au fichier CLIENT de JOBIPF.

CRTPF ajoute aussitôt un membre du même nom. Sans autre précision, le fichier est créé avec SIZE(10000 1000 3), REUSEDLT(*NO) et MAXMBRS(1), trois valeurs relevées sur le fichier et qui comptent dans la comparaison avec SQL.

Ajouter, modifier, supprimer avec UPDDTA

UPDDTA crée un programme DFU temporaire, construit à partir de la description du fichier : pas une ligne de code à écrire. Il s'ouvre en mode MODIFICATION, avec les en-têtes COLHDG des DDS :

UPDDTA  FILE(JOBIPF/CLIENT)
Écran 5250 Gestion de données d'un fichier, mode Modification, format CLIENTR, fichier CLIENT : zones Numero client, Nom, Ville, Cat, Solde vides ; F9=Insertion, F10=Saisie, F11=Modification
L'écran d'UPDDTA : les libellés viennent du mot-clé COLHDG des DDS.

Ajouter : F10

F10 passe en mode SAISIE. On tape un nouveau client… avec la catégorie « Z », hors de la liste VALUES. Dans une zone numérique, la touche Fin de zone (Field Exit) cadre la valeur à droite : 4510 donne 45,10 avec les deux décimales du format.

Écran 5250 en mode Saisie : Numero client 500, Nom Petit Atelier, Ville Lyon, Cat Z, Solde 4510
Saisie du client 500, catégorie Z.
Écran 5250 en mode Saisie, message en bas : Valeur de zone entrée incorrecte. Valeurs correctes dans l'aide du message.
UPDDTA applique VALUES : « Valeur de zone entrée incorrecte ».

Corrigée en « B », la saisie est acceptée et l'écran se vide pour le client suivant.

Modifier : F11

F11 revient en mode MODIFICATION : on tape la clé (ici 200, suivie de Fin de zone), Entrée affiche l'enregistrement, on change les zones, Entrée met à jour.

Écran 5250 en mode Modification : client 200, Martin et fils, ville changée en Villeurbanne, catégorie B, solde 15000
Le client 200 passe à Villeurbanne, avec un solde de 150,00.

Supprimer : F23, deux fois

Toujours en modification, on affiche le client 900 puis on appuie sur F23 : UPDDTA demande confirmation par un second F23.

Écran 5250 en mode Modification : client 900, Essai categorie, Brest, Cat Z ; message : Faites F23 pour confirmer la demande de suppression de l'enregistrement.
Premier F23 : la demande de confirmation.

F3 termine et affiche le bilan de la séance :

Écran 5250 Saisie de données - Fin : Ajoutés 1, Modifiés 1, Supprimés 1 ; Fin de la saisie de données O
Un ajout, une modification, une suppression.

Le programme d'UPDDTA disparaît à la fin de la séance ; pour un programme DFU que l'on conserve et que l'on adapte, on passe par STRDFU.

Voir le contenu, et la place des supprimés

DSPPFM affiche le membre tel qu'il est stocké :

Écran 5250 Membre de fichier physique CLIENT de JOBIPF : quatre enregistrements, noms et villes lisibles, numéros et soldes illisibles
DSPPFM : les zones condensées (numéro, solde) ne sont pas lisibles en clair.

Les zones décimales condensées y sont illisibles : DSPPFM montre les octets. Pour lire des valeurs, une requête suffit, car un PF se lit en SQL comme une table :

SELECT * FROM JOBIPF.CLIENT ORDER BY NUMCLI

Les enregistrements supprimés, eux, n'ont pas disparu du disque. Après deux suppressions, le service QSYS2.SYSPARTITIONSTAT en comptait 2 (NUMBER_DELETED_ROWS) : avec REUSEDLT(*NO), leur place reste perdue. RGZPFM la récupère :

RGZPFM  FILE(JOBIPF/CLIENT)
CPC2983  Données du membre CLIENT réorganisées.

Après la réorganisation : 4 enregistrements, 0 supprimé.

La même table en SQL

CREATE TABLE JOBIPF.CLIENT_EN_SQL FOR SYSTEM NAME CLIENTSQL (
  NUMCLI DECIMAL(5, 0) NOT NULL,
  NOM    CHAR(30)      NOT NULL DEFAULT '',
  VILLE  CHAR(20)      NOT NULL DEFAULT '',
  CATEG  CHAR(1)       NOT NULL DEFAULT 'A',
  SOLDE  DECIMAL(9, 2) NOT NULL DEFAULT 0,
  CONSTRAINT JOBIPF.CLIENT_EN_SQL_PK PRIMARY KEY (NUMCLI),
  CONSTRAINT JOBIPF.CLIENT_EN_SQL_CATEG CHECK (CATEG IN ('A', 'B', 'C'))
) RCDFMT CLIENTSQLR

Les en-têtes et les textes des DDS deviennent des LABEL ON :

LABEL ON TABLE JOBIPF.CLIENT_EN_SQL IS 'Clients (SQL)';
LABEL ON COLUMN JOBIPF.CLIENT_EN_SQL (
  NUMCLI IS 'Numero              client', NOM IS 'Nom', VILLE IS 'Ville',
  CATEG IS 'Cat', SOLDE IS 'Solde');
LABEL ON COLUMN JOBIPF.CLIENT_EN_SQL (
  NUMCLI TEXT IS 'Numero du client', NOM TEXT IS 'Raison sociale',
  CATEG TEXT IS 'Categorie A, B ou C');

Deux pièges rencontrés en l'écrivant : FOR SYSTEM NAME est refusé (SQL7029) quand le nom long est déjà un nom système valide, comme CLIENT_SQL ; et un nom de contrainte non qualifié se range dans le schéma courant, d'où SQL5051 tant qu'il n'est pas préfixé par JOBIPF..

Les opérations faites dans UPDDTA s'écrivent ainsi :

INSERT INTO JOBIPF.CLIENT_EN_SQL (NUMCLI, NOM, VILLE, CATEG, SOLDE)
  VALUES (500, 'Petit Atelier', 'Lyon', 'B', 45.10);

UPDATE JOBIPF.CLIENT_EN_SQL
   SET VILLE = 'Villeurbanne', SOLDE = 150
 WHERE NUMCLI = 200;

DELETE FROM JOBIPF.CLIENT_EN_SQL WHERE NUMCLI = 900;

Ces instructions marchent aussi sur le PF créé en DDS : SQL lit et modifie tous les fichiers physiques. Le service QSYS2.SYSFILES le confirme : les deux objets ont le type natif PHYSICAL ; seule la table SQL porte en plus le type SQL TABLE.

PF DDS et table SQL : les différences démontrées

PointPF créé en DDSTable créée en SQL
DéfinitionSource DDS en colonnes, compilée par CRTPFInstruction CREATE TABLE
Données écritesPas vérifiées : un SOLDE fait de blancs est acceptéVérifiées à l'écriture : CPF5029, rien n'est écrit
Valeurs permisesVALUES ne joue qu'à la saisie écran (UPDDTA) ; un INSERT passeContrainte CHECK : SQL0545 pour tout le monde
TailleSIZE(10000 1000 3) : 13 000 enregistrements, supprimés compris, puis message à l'opérateur systèmePas de limite fixée (*NOMAX)
Enregistrements supprimésPlace perdue jusqu'au RGZPFM (REUSEDLT(*NO))Place réutilisée (REUSEDLT(*YES))
Noms10 caractères (ALIAS donne un nom long à une zone)Noms longs pour la table et les colonnes, avec un nom système de 10 caractères
CléMot-clé UNIQUE et zone KClé primaire (PRIMARY KEY), contraintes nommées
JournalisationPas automatique : STRJRNPF, ou STRJRNLIB sur la bibliothèqueAutomatique si la table est créée dans un schéma SQL (journal QSQJRN)

1. Les données invalides

C'est la différence qui compte le plus. Nous avons fabriqué un enregistrement brut de 59 octets dont le SOLDE contient cinq blancs (x'4040404040') au lieu d'un nombre condensé, puis nous l'avons copié dans les deux fichiers avec CPYF … FMTOPT(*NOCHK) :

Vers le PF DDS    : CPC2955  1 enregistrement(s) du membre PLAT copié(s).
Vers la table SQL : CPF5029  (erreur de mappage de données)
                    CPF2972  Erreur d'écriture dans le membre CLIENTSQL du fichier CLIENTSQL.

La table SQL vérifie les données à l'écriture et refuse. Le PF DDS les accepte, et l'erreur n'apparaît qu'à la lecture, chez le premier qui lit l'enregistrement. Un programme RPG qui parcourt le fichier :

**free
// Lit le PF CLIENT enregistrement par enregistrement et affiche le solde.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-f client keyed;

read client;
dow not %eof(client);
  snd-msg 'Client ' + %char(numcli) + ' : solde ' + %char(solde);
  read client;
enddo;

*inlr = *on;
Client 100 : solde 1250.50
Client 200 : solde .00
Client 300 : solde -320.00
MCH1202  Erreur dans une donnée décimale.
RNQ0907  (C G D F) Erreur de données décimales.

Il s'arrête sur le client 400. En SQL, c'est plus sournois : la requête ne s'arrête pas. Le SOLDE du client 400 revient à NULL, et seul un message d'information SQL0802 (« Erreur de conversion ou de mappage des données ») reste dans l'historique du travail, avec CPF5035. Une somme sur tout le fichier, SELECT SUM(SOLDE), rend elle aussi NULL, sans erreur, alors que quatre soldes sur cinq sont corrects.

2. VALUES n'est pas une contrainte

UPDDTA a refusé la catégorie Z, mais un INSERT SQL dans le même PF DDS l'a acceptée sans broncher. IBM le précise : les mots-clés de contrôle de validité des DDS (VALUES, RANGE) ne sont vérifiés que lors d'une saisie sur un écran. La contrainte CHECK de la table SQL, elle, s'applique à tous :

INSERT INTO JOBIPF.CLIENT VALUES (900, 'Essai categorie', 'Brest', 'Z', 0)
  -> accepté
INSERT INTO JOBIPF.CLIENT_EN_SQL VALUES (900, 'Essai categorie', 'Brest', 'Z', 0)
  -> SQL0545  INSERT, UPDATE ou MERGE non admis pour une contrainte CHECK.

3. La place des enregistrements supprimés

Sur la table SQL, après une suppression, NUMBER_DELETED_ROWS valait 1 ; l'INSERT suivant l'a ramené à 0 : la place a été réutilisée, conformément à REUSEDLT(*YES). Sur le PF, il a fallu RGZPFM.

Un PF DDS n'est pas « moins bien » à lire. Un programme RPG ou une requête SQL le traitent comme une table. La différence est à l'écriture : rien n'empêche un programme, une copie ou un transfert d'y déposer des octets faux, qui ne se révèlent qu'à la lecture : d'où les MCH1202 qu'on rencontre encore sur des fichiers anciens. Pour un nouveau fichier, nous conseillons donc SQL.

À retenir

  • Les DDS (System/38, 1978) donnent une description unique des données, rangée avec le fichier.
  • Un PF : un format, des membres, des données ; CRTPF compile la source DDS.
  • UPDDTA : F10 saisie, F11 modification, F23 deux fois pour supprimer, Fin de zone dans les zones numériques.
  • Une table SQL est aussi un PF, mais elle vérifie les données à l'écriture, applique ses contraintes CHECK et réutilise la place des supprimés.

Sources

Les exemples ont été créés et relevés sur un IBM i 7.5 (voir la méthode). Les définitions et les règles viennent de ces sources, consultées le 16 octobre 2026 :

  1. IBM System/38 Technical Developments : File and data definition facilities in System/38, IBM, C. D. Truxal et S. R. Ridenour (1978, PDF numérisé). Les descriptions de données redondantes et divergentes d'avant (« each program … has required a separate definition of the data »), la description centrale par les DDS réutilisée par les compilateurs et les utilitaires, le contrôle de niveau, les fichiers décrits dans le programme conservés pour la conversion, les PF à un seul format et leurs membres. Le même recueil contient l'article de Conway et Harvey sur le choix d'un formulaire déclaratif séparé du programme, et l'indépendance des programmes vis-à-vis de la structure physique grâce aux fichiers logiques ; le LF qui fait suivre chaque en-tête de ses lignes de détail.
  2. IBM Structured Query Language/400 : Programmer's Guide (SC21-9609-1), IBM (1988, 1989, PDF numérisé). Le SQL sur AS/400 sous forme de programme sous licence SQL/400 (5728-ST1), copyright 1988.
  3. IBM i 7.5 Database : Database programming, IBM (PDF). Fichiers physiques et logiques, membres, REUSEDLT, mots-clés de contrôle de validité (VALUES, RANGE) appliqués seulement à la saisie sur un écran.
  4. IBM i 7.2 Programming : DDS for physical and logical files, IBM (PDF). Positions de la spécification DDS (17 type de nom, 19 à 28 nom, 30 à 34 longueur, 35 type, 36 et 37 décimales, 45 à 80 mots-clés), mots-clés UNIQUE, TEXT, COLHDG, VALUES, EDTCDE.
  5. IBM i 7.5 Database : SQL programming, IBM (PDF). Tables SQL créées avec REUSEDLT(*YES), journalisation automatique dans QSQJRN pour une table créée dans un schéma.
  6. L'aide en ligne des commandes citées, livrée avec IBM i 7.5 et reprise en français dans les fiches des commandes CL de ce site. Paramètres de CRTPF, CRTLF, CRTSRCPF, ADDPFM, OVRDBF, UPDDTA, DSPPFM, RGZPFM, CPYF, CRTBNDRPG et CRTBNDCL.

Questions fréquentes

Qu'est-ce qu'un PF sur IBM i ?

Un fichier physique (physical file) est l'objet *FILE qui contient réellement les données d'une table : un format d'enregistrement (la liste des zones), les enregistrements, rangés dans un ou plusieurs membres, et éventuellement un chemin d'accès par clé. Une table créée en SQL est elle aussi un fichier physique.

Pourquoi IBM a-t-il inventé les DDS ?

Pour le System/38, annoncé en 1978. Auparavant, chaque programme décrivait lui-même les données qu'il lisait, et ces descriptions différaient d'un programme à l'autre. Les DDS donnent une description unique, rangée avec le fichier et réutilisée par les compilateurs, les utilitaires et les commandes, sous la forme d'un formulaire en colonnes, comme le RPG de l'époque.

Comment créer un fichier physique ?

On écrit sa description en DDS dans un membre de type PF d'un fichier source (QDDSSRC), puis on lance CRTPF FILE(bib/fichier) SRCFILE(bib/QDDSSRC). En SQL, CREATE TABLE crée directement le fichier physique.

Comment modifier les données d'un PF sans programme ?

Avec UPDDTA FILE(bib/fichier), qui crée un programme DFU temporaire : F10 pour saisir de nouveaux enregistrements, F11 pour modifier ou supprimer (F23, deux fois) après avoir tapé la clé. En SQL, INSERT, UPDATE et DELETE font la même chose, sur un PF comme sur une table.

Faut-il encore créer ses fichiers en DDS ?

Pour un nouveau fichier, SQL apporte plus de contrôles : données vérifiées à l'écriture, contraintes CHECK, noms longs, pas de limite de taille fixée. Les PF existants décrits en DDS restent pleinement utilisables, en RPG comme en SQL, et il faut savoir les lire.

Pourquoi mes enregistrements supprimés prennent-ils encore de la place ?

Un PF créé par CRTPF ne réutilise pas la place des enregistrements supprimés (REUSEDLT(*NO) par défaut) : elle reste perdue jusqu'à un RGZPFM. Une table créée en SQL réutilise cette place (REUSEDLT(*YES)).