Voici 5 fonctions qui peuvent vous intéresser pour manipuler des dates en SQL.
je vous rappelle que pour les utiliser, vos zones doivent être au format date et si ce n’est pas le cas vous devrez utiliser la fonction date pour vous mettre dans le format attendu Exemple : values date(‘2012-01-01’)
Il est fortement conseillé si manipulez des dates de vous mettre dans un format *ISO pour éviter les problèmes de bascule des dates à 6 positions
1) Vous avez besoin de connaitre le premier jour du mois Vous avez la fonction FIRST_DAY() values FIRST_DAY(‘2012-12-12’) ; renverra 2012-12-01
pour le jour en cours FIRST_DAY(current date) = current date
2) Vous avez besoin de connaitre le dernier jour du mois Vous avez la fonction LAST_DAY() values LAST_DAY(‘2012-12-12’) ; renverra 2012-12-31
Pour le jour en cours LAST_DAY(current date) = current date
3) Vous voulez connaitre le numéro du jour dans l’année , le rang julien Vous avez la fonction DAYOFYEAR()
values DAYOFYEAR(‘2012-12-12’) renverra 347
4) Connaitre le jour de la semaine Vous avez la fonction DAYOFWEEK() elle vous renverra un numéro de 1 à 7 qui est le numéro du jour dans la semaine attention 1 c’est le dimanche values DAYOFWEEK(‘2012-12-12’) vous renverra 4 Si vous voulez commencer le lundi values DAYOFWEEK(‘2012-12-12’) – 1 , attention bien sur, un dimanche vous aurez 0
5) Connaitre le nombre de jours depuis le premier janvier 01
Vous avez la fonction DAYS()
values DAYS(‘2012-12-12’) renverra 734849 Cette fonction sert souvent pour calculer le nombre de jours entre 2 dates
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2025-01-27 10:42:242025-01-28 10:21:085 Astuces SQL sur les dates
SQL_DB2Lire facilement les données dans le journal d’un fichier
La journalisation des fichiers peut vous fournir plein d’informations notamment sur les modifications de données.
Pour exploiter ces informations, vous pouvez utiliser
le DSPJRN historique
la fonction table SQL QSYS2.DISPLAY_JOURNAL
Mais dans les 2 cas nous trouvons face à la complexité de la gestion de la zone entry_data qui contient un buffer complet de votre enregistrement base de données.
Nous proposons depuis longtemps l’outil gratuit ANAJRN que vous pouvez télécharger ici :
Le principe est le suivant, vous devez avoir le compilateur RPG sur votre partition, puisqu’il compile dynamiquement le programme de sortie.
Mais pour faire plus Kevin et moins Robert, j’ai mis au point une méthode à base de SQL qui nous permet d’arriver au même résultat.
La table NKSQL.STAGIAIRE a été crée et journalisée :
CREATE TABLE nksql.stagiaire
(
numero_stagiaire FOR COLUMN numstag int NOT NULL WITH DEFAULT,
nom_stagaire FOR COLUMN nomstag CHAR ( 50) NOT NULL WITH DEFAULT,
prenom_stagaire FOR COLUMN prestag CHAR ( 50) NOT NULL WITH DEFAULT,
date_entree FOR COLUMN datent DATE NOT NULL WITH DEFAULT,
PRIMARY KEY (numero_stagiaire)
) ;
Quelques actions sur la table pour alimenter le journal :
INSERT INTO NKSQL.STAGIAIRE VALUES(5, 'da Caravaggio', 'Michelangelo', date(now()));
UPDATE NKSQL.STAGIAIRE SET date_entree = '2024-12-06' WHERE numero_stagiaire = 2;
INSERT INTO NKSQL.STAGIAIRE VALUES(6, 'Magritte', 'René', date(now()- 2 months)) ;
DELETE FROM NKSQL.STAGIAIRE WHERE numero_stagiaire = 6;
L’exemple est prêt, retrouvons les données !
D’abord il faut retrouver le journal, et tant qu’à avoir SQL ouvert, j’utilise QSYS2.OBJECT_STATISTICS :
select objlib,
objname,
journal_library,
journal_name,
journal_images,
omit_journal_entry,
journal_start_timestamp
from table(qsys2.object_statistics('NKSQL', '*FILE', 'STAGIAIRE'))
where journaled = 'YES';
Ensuite il faut extraire ce journal. Dans un fichier temporaire ou non :
CREATE OR REPLACE TABLE qtemp.extrac_jrn AS (
SELECT journal_code,
journal_entry_type,
entry_timestamp,
user_name,
job_name,
job_number,
program_name,
entry_data
FROM TABLE (QSYS2.DISPLAY_JOURNAL(JOURNAL_LIBRARY =>'NKSQL',
JOURNAL_NAME =>'QSQJRN',
STARTING_RECEIVER_LIBRARY =>'*CURCHAIN',
JOURNAL_CODES =>'R',
OBJECT_LIBRARY =>'NKSQL',
OBJECT_NAME =>'STAGIAIRE',
OBJECT_OBJTYPE =>'*FILE',
OBJECT_MEMBER =>'STAGIAIRE')
) AS X
ORDER BY entry_timestamp DESC)
WITH DATA ON REPLACE DELETE ROWS;
On peut consulter cette extraction de journal, mais les données de enrty_data ne sont pas lisibles
SELECT * FROM qtemp.extrac_jrn ;
La requête qui suit va permettre de nous donner l’outil d’interprétation spécifique à cette table :
select
case
when data_type = 'DATE' then 'date(interpret(substr(entry_data, '
when data_type = 'TIMESTMP' then 'timestamp(interpret(substr(entry_data, '
else 'interpret(substr(entry_data, '
end concat
case
when ordinal_position = 1 then '1'
else
(select trim(char(sum(case when data_type = 'DATE' then storage+6 when data_type = 'TIMESTMP' then storage+16 else storage end))+1)
from qsys2.syscolumns c
where a.system_table_name = c.system_table_name
and a.system_table_schema = c.system_table_schema
and a.ordinal_position > c.ordinal_position)
end concat
', ' concat
case
when data_type = 'DATE' then '10'
when data_type = 'TIMESTMP' then '26'
else trim(char(storage))
end concat
') as ' concat
case
when data_type in( 'TIMESTMP', 'DATE') then 'CHAR'
else trim(data_type)
end concat
case
when data_type = 'BIGINT' then ''
when data_type = 'NUMERIC' then '(' concat trim(char(a.length)) concat ', ' concat trim(char(numeric_scale)) concat ')'
when data_type = 'DECIMAL' then '(' concat trim(char(a.length)) concat ', ' concat trim(char(numeric_scale)) concat ')'
when data_type = 'CHAR' then '(' concat trim(char(a.length)) concat ')'
when data_type = 'INTEGER' then ''
when data_type = 'TIMESTMP' then '(26)'
when data_type = 'DATE' then '(10)'
end concat
Case
when data_type in ('DATE', 'TIMESTMP') then ')) '
else ') as '
end concat
trim(system_column_name) concat
',' as interpretation
from qsys2.syscolumns a
join qsys2.sysfiles b
on a.system_table_name = b.system_table_name
and a.system_table_schema = b.system_table_schema
where b.native_type = 'PHYSICAL'
and b.file_type = 'DATA'
and b.system_table_name = 'STAGIAIRE'
and b.system_table_schema = 'NKSQL'
order by ordinal_position;
Ce resulset, à une virgule près, est intégré dans la requête de visualisation de qtemp.extrac_jrn :
select journal_entry_type,
entry_timestamp,
user_name,
job_name,
job_number,
program_name,
-- à la suite le copier coller du resultset de la requête précédente :
interpret(substr(entry_data, 1, 4) as INTEGER) as NUMSTAG,
interpret(substr(entry_data, 5, 50) as CHAR(50)) as NOMSTAG,
interpret(substr(entry_data, 55, 50) as CHAR(50)) as PRESTAG,
date(interpret(substr(entry_data, 105, 10) as CHAR(10))) DATENT
from qtemp.extrac_jrn;
On voit bien les deux créations, la mise à jour et la suppression d’enregistrement.
La partie la plus utile de cet article est celle qui produit les interpret à partir de QSYS2.SYSCOLUMNS et QSYS2.SYSFILES. Pour l’instant elle a bien fonctionné sur toutes les tables/fichiers que j’ai rencontré mais vous pouvez certainement l’améliorer !
Vous pouvez aussi directement inclure les interpret de la dernière requête dans celle du DISPLAY_JOURNAL.
/wp-content/uploads/2017/05/logogaia.png00Nicolas kintz/wp-content/uploads/2017/05/logogaia.pngNicolas kintz2025-01-21 08:51:132025-01-21 08:51:15Lire facilement les données dans le journal d’un fichier
Vous connaissez les fonctions usage qui vous permettent de sécuriser votre système IBMi
Exemple , accès au fichier
Elles sont organisées par famille
Voici les principales
Base operating system (5770SS1) TCP/IP connectivity utilities (5770TC1) Backup, Recovery, and Media Services (BRMS) (5770BR1 5770BR2) IBM i Access Client Solutions (ACS) (5770XJ1) IBM Navigator for i
Vous avez un site de référence qui va vous permettre de vous y retrouver c’est ici
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2025-01-20 20:23:012025-01-20 20:23:02Trouver la fonction usage que vous cherchez ?
Vous connaissez tous la notion de liste de bibliothèques qui existe sur l’ibmi
la même notion existe sous unix c’est le path, et qui impacte vos commandes exécutées par exemple à partir de QSH
Vous pouvez le changer temporairement, voici la commande par exemple qui prend votre PATH et lui ajoute l’accès au commande open source de votre machine
Vous pouvez le changer de maniére dénitive pour une utilisateur
En créant un fichier .profile à la racine de votre path
Ca devrait donner ca /home/<votreuser>/.profile
Vous lui ajouter ces commandes
# Mise en ligne commande Open source PATH=/QOpenSys/pkgs/bin:$PATH export PATH PASE_PATH
Vous pouvez le changer globalement pour votre partition
Vous devez créer le fichier /etc/profile et lui ajouter ces lignes
# Mise en ligne commande Open source en plus des commandes standards export PATH=/usr/bin:.:/QOpenSys/usr/bin
Remarque :
Vous pouvez également travailler en hardcodant , ce n’est pas conseillé pour des raisons de maintenance exemple une copie de clé publique /QOpenSys/pkgs/bin/ssh-copy-id ….
Vous pouvez également utiliser la variable d’environnement PATH
Bien sur si vous décidez d’utiliser le fichier etc/profile ou la variable d’environnement PATH avec portée *SYS, pensez à l’impact global sur votre système
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2025-01-03 09:50:482025-01-04 10:12:10PRUV et le cloud
Vous avez souvent sur vos machines de développements beaucoup d’objets à l’intérieur
Vous avez sans doute remarqué que quand vous compiler un objet et qu’il a des erreurs , il vous remet l’ancienne version.
Comment cela est il possible ?
A chaque compile l’objet est renommé est placé dans une bibliothèque qui s’appelle QRPLOBJ
Voici un schéma pour vous expliquer
Cette bibliothèque est clearée à chaque IPL
Pour connaitre la taille de la bibliothèque vous pouvez par exemple utiliser cette requête :
SELECT LIBRARY_SIZE FROM TABLE(QSYS2.LIBRARY_INFO(‘QRPLOBJ’))
Si elle grossit trop vous devrez faire un coup de ménage, attention elle est interdite par défaut il faut être *ALLOBJ pour faire cette opération
PS :
Vous avez aussi à l’intérieur des objets de type USRQ, USRSPC, c’est souvent sur les CRTxx ou vous pouvez indiquer REPLACE(*YES) sur l’API ou la commande …
Attention Vérifiez bien votre résultat de compile avant de relancer votre programme sinon vous lancez une vielle version !
Au verrouillage , mais normalement vous ne devriez pas avoir d’objets verrouillés à l’intérieur ca peut indiquer un autre dysfonctionnement puisque cet objet sera effacé à l’IPL !
La préconisation d’IBM et de faire IPL à chaque application de PTFs pour ne pas perdre le cache SQL par exemple
Mais, il y a quand même un point, pour vous inviter à en faire plus, c’est la mémoire qui est perdu sur certain travaux
Vous avez une vue QSYS2.SYSTMPSTG qui permet de voir les buckets
La vue SYSTMPSTG contient une ligne pour chaque espace de stockage temporaire qui contient une quantité de stockage temporaire sur le système. Le stockage temporaire est un stockage qui ne persiste pas lors d’un redémarrage du système d’exploitation. on parle de « BUCKET »
Voici une requête qui montre l’espace perdu par les jobs terminés
SELECT ‘Perdu’ as memoire , sum(BUCKET_CURRENT_SIZE) as taille FROM qsys2.SYSTMPSTG WHERE JOB_STATUS = ‘*ENDED’
le détail
SELECT JOB_NAME, JOB_USER_NAME, JOB_NUMBER , BUCKET_CURRENT_SIZE FROM qsys2.SYSTMPSTG WHERE JOB_STATUS = ‘*ENDED’ order by BUCKET_CURRENT_SIZE desc
Voici une requête qui donne la taille totale
SELECT ‘Total’ as memoire , sum(BUCKET_CURRENT_SIZE) as taille FROM qsys2.SYSTMPSTG ;
Vous pouvez faire un ratio et si il est important 10 % par exemple
Vous devrez faire une IPL, pour récupérer cette mémoire
Vue dans Navigator For I
Ps: A ce jour il n’y a pas d’autres solutions pour récupérer cette mémoire
pour en savoir plus : https://www.ibm.com/support/pages/how-often-ipl-should-be-performed
Voici comment visualiser l’historique d’une macro-commande Arcad
Objectifs :
Lorsqu’une macro-commande se termine en anomalie, la joblog peut ne pas être toujours évidente à décrypter ou pire elle peut avoir été supprimée.
Cet article a pour objectif de présenter process à suivre pour pouvoir visualiser chaque étape d’exécution d’une macro-commande Arcad.
Pour cela il faut :
Retrouver l’instance de la macro commande à analyser
Afficher l’historique de l’instance à analyser
1) Recherche de l’instance de la macro-commande à analyser :
Lancer la commande AWRKMACCMD pour accéder à la liste des macro-commandes Arcad.
Lancer l’option 5 AFFICHER sur la macro-commande concernée.
Une fois la macro-commande affichée :
Faire F9 pour afficher toutes les instances de lancement de la macro-commande
La liste des instances d’exécution de la macro-commande s’affiche.
Dans l’exemple ci-dessus on voit que la 25eme instance n’a pas abouti (Etat à ABN = Abandon).
La touche F11 permet de changer de vue et ainsi afficher les dates de traitement, cela facilite l’identification précise de l’instance à analyser.
2) Afficher l’historique de l’instance à analyser
Lancer l’option 13 (Historique) sur l’instance à analyser
L’historique des commandes de la macro-commande sera alors affiché
Pour rappel :
Les lignes en rouge correspondent aux alertes Arcad Attention : ce ne sont pas toujours des anomalies.
La touche F8 permet d’afficher l’intégralité de la commande Arcad sur laquelle est positionné le curseur. Cela permet de visualiser toute la commande avec tous ses paramètres
La touche F16 permet de rechercher une chaine de caractères dans l’ensemble des commandes affichées. Les lignes contenant la chaine de caractères recherchées seront affichées en surbrillance.
Le nombre d’occurrences trouvées sera affiché en bas de l’écran.