Cartes ENC dans QGis avec Postgis(1)

Ce sujet comporte deux articles. Le premier aborde l’import de fichiers ENC S57 dans une base de données Postgresql/postgis. Le deuxième, la mise en place d’une symbologie automatique équivalente aux cartes marines. Vous pouvez télécharger l’ensemble des scripts de cet article à l’adresse https://www.nasca.ovh/downloads/fichiers_enc_postgis1.7z ou accéder directement sur GItHub: https://github.com/SigEtTerritoires/enc_postgis

Nous vous conseillons de décompresser tous les fichiers sql (.sql) et batch (.bat) dans un répertoire de votre choix, en sachant que pour leur utilisation vous devrez changer le répertoire utilisé dans les scripts par le nom de votre répertoire.
Pour la symbologie, comme vous verrez plus loin vous aurez le choix de créer soit un répertoire par défaut :C:/nautical ((recommandé), soit un répertoire de votre choix
.

Le format S57 et les SIG

Si vous vous lancez à travailler avec des fichiers S57 dans un SIG, il y a quelques éléments que vous devez connaître pour naviguer sans écueils.

Tout d’abord, la structure des fichiers S57 ne répond pas aux structures adoptées dans les SIG.

Dans un SIG vous avez un objet géographique qui est représenté par une table avec deux types d’informations : la géométrie des entités de l’objet et les attributs de ces entités.

Si vous avez d’autres objets qui ont des géométries identiques, l’information géométrique est dupliquée, une fois dans chaque table.

Pour le format S57 l’objectif principal est d’optimiser le stockage des informations et par conséquent de ne pas dupliquer les informations. Si un objet a une entité ponctuelle, un point sera créé. Du moment ou d’autres objets ont des entités situées sur ce point, on utilisera la référence du point qui a déjà été créé. De cette manière un point n’est décrit qu’une seule fois dans le fichier. Il en va de même pour les polylignes et les surfaces. Un fichier S57 aura donc une série de tables contenant l’information géométrique, dénommées « primitives » :

  • IsolatedNode (points)
  • ConnectedNode (points)
  • Edge (polylignes)
  • Face (polygones)

La table attributaire des différents objets S57 contient seulement les attributs des objets.

Les types de géométrie

Les « couches » S57 sont des classes d’objets. Par exemple, les différentes zones terrestres sont codées dans la classe d’objets LNDARE.

La définition de cette classe d’objets est :

Geo object: Land area (LNDARE) (P,L,A)
Attributes: CONDTN OBJNAM NOBJNM STATUS INFORM NINFOM

Si tous les objets LNDARE possèdent les mêmes attributs, il n’en est pas de même du type de géométrie. L’information (P, L, A) indique que, dans cette classe d’objets on peut trouver des points, des lignes et des polygones. Contrairement aux standards SIG, les trois types de géométrie coexistent au sein de la même classe d’objets.

Pour passer du format S57 a une base Postgresql/Postgis nous utiliserons la bibliothèque GDAL, incluse avec QGis.

Les opérations avec GDAL seront effectuées par ligne de commande dans une fenêtre OSGeo4W.

La syntaxe de base pour traiter un fichier S57 (extension .000) et l’importer dans une base de données Postgtresql/Postgis est la suivante :

ogr2ogr -f PostgreSQL PG:"dbname='postgis_34_sample' host='localhost' port='5434' user='postgres' password='psw' active_schema='schema'" fichier.000

Nous verrons les différentes options à utiliser et leur fonction, mais d’ores et déjà nous ajouterons les options -skipfailures -append –update.

ogr2ogr -skipfailures -append –update  -f PostgreSQL PG:"dbname='postgis_34_sample' host='localhost' port='5434' user='postgres' password='psw' active_schema='schema'" fichier.000

La première permet de continuer le traitement même si des erreurs sont détectées. Les deux suivantes permettent de ne pas écraser les tables postgresql en sortie si elles existent mais de les mettre à jour en ajoutant les données du fichier S57 en entrée.

Quel qu’il soit le format choisi pour l’intégrer dans QGis, nous aurons à créer une couche par type de géométrie. Si on ne le fait pas, GDAL va créer le type de couche en fonction de la première entité trouvée lors de la conversion. Si elle est de type point, la couche créée sera de type point et les entités lignes et polygones seront ignorées. De même, si la première est de type ligne, ce seront les points et les polygones qui seront ignorés.

Il faut aussi noter que le format S57 n’a aucune contrainte sur les classes d’objets : si dans la zone couverte par le fichier S57 il n’y a pas une classe d’objet, il n’y aura rien la concernant dans le fichier (pas de couche vide). De même, s’il n’y a qu’un type de géométrie présente, alors que les trois types sont possibles, il n’y aura pas de trace des autres types de géométrie.

Il faudra alors décomposer le traitement d’un fichier S57 avec ogr2ogr en trois étapes, une pour chaque type de géométrie. Les options suivantes permettent de traiter chaque classe d’objet S57 en ne sélectionnant qu’un type de géométrie :

-where « OGR_GEOMETRY=’POINT’ or OGR_GEOMETRY=’MULTIPOINT’ »

-where « OGR_GEOMETRY=’LINESTRING’ or OGR_GEOMETRY=’MULTILINESTRING’ »

-where « OGR_GEOMETRY=’POLYGON’ or OGR_GEOMETRY=’MULTIPOLYGON’ »

GDAL permet pour certains types de drivers de créer des préfixes dans les tables en sortie. Dans ce cas on pourrait créer toutes les tables (points, lignes, polygones) dans un seul schéma en les préfixant par exemple avec pt_, li_ et pl_. Le problème est que le driver S57 de GDAL ne permet pas cette option. On doit alors créer trois schémas distincts, dans lesquels les tables seront créées selon le type de géométrie. Dans chaque schéma il y aura alors une table de même nom mais de géométrie différente.

Nous allons utiliser ici trois schémas d’import pour les commandes ogr2ogr dans lesquels nous allons importer les tables d’un fichier S57. Nous les appellerons pointsenc, linesenc et polysenc. D’autre part nous allons créer un schéma appelé ENC pour la base de données complète. Pour chaque carte ENC nous allons importer son contenu dans les trois schémas d’import avec ogr2ogr puis nous allons exécuter des requêtes SQL pour mettre à jour la base de données du schéma ENC avec les nouvelles tables importées. Que vous ayez un seul fichier S57 à charger ou bien un lot de fichiers S57 à charger simultanément, le processus est le suivant :

  1. Chargement des classes d’objets Point dans le schéma pointsENC avec ogr2ogr
  2. Chargement des classes d’objets Lignes dans le schéma LinesENC avec ogr2ogr
  3. Chargement des classes d’objets Polygone dans le schéma PolysENC avec ogr2ogr
  4. Suppression des tables vides des trois schémas
  5. Mise à jour des tables existantes dans le schéma ENC à partir des trois schémas d’import
  6. Clonage des tables des trois schémas d’import qui n’étaient pas présentes dans le schéma ENC,
  7. Suppression des tables des trois schémas d’import

Le traitement des sondes bathymétriques

Les sondes bathymétriques posent plusieurs problèmes lors de la conversion de format. Le premier est que la valeur de profondeur n’est pas une contenue dans un attribut, mais en tant que Z dans la géométrie (XYZ). Le deuxième est que les sondes ne sont pas du type Point mais Multipoint. Pour avoir directement la valeur des sondes dans un champ attributaire, il faut donc ajouter deux paramètres à la ligne de commande ogr2ogr:

-oo SPLIT_MULTIPOINT=ON -oo ADD_SOUNDG_DEPTH=ON

Le premier converti les entités multipoint en points individuels, et le deuxième ajoute un champ attributaire « DEPTH » à la table en sortie avec la valeur Z de la géométrie.

Récupération des identifiants « parents »

Certains objets peuvent être regroupés par un objet non géographique parent. Par exemple, les secteurs de feu sont codés avec un secteur par enregistrement de la table « LIGHTS ». Les différents secteurs d’un même feu n’ont aucun attribut particulier qui puisse indiquer qu’ils correspondant à la même entité. Cette information se trouve dans un enregistrement « parent ». Pour récupérer cet identifiant en tant qu’attribut de la table LIGTHS, il faut ajouter une option à la ligne de commande :

-oo RETURN_LINKAGES=O

Cette option crée un attribut name_rcid qui est commun à tous les secteurs d’un même feu, mais créé aussi une série de champs (name_rcnm,ORNT,USAG,MASK).

Le traitement des type « Liste »

Le format S57 utilise, en plus des types de champ classiques (entier, réel, texte) un type particulier : les listes de chaînes de caractères ou d’entiers. Si on retrouve ces types de champ dans PostgreSQL, il n’en va pas de même dans les shapefiles et le geopackage. Il n’est donc pas nécessaire de transformer les listes S57 en chaînes de caractères comme pour ces formats. Il est même fortement déconseillé car cela compliquerait le traitements des attributs de type liste.

Gestion des doublons d’information

Quand vous chargez plusieurs cartes ENC dans une même base de données vous pouvez vous confronter à une duplication des informations quand l’emprise de deux ou plusieurs cartes se superposent.

Ces doublons peuvent être de deux types différents :

  • Des « vrais » doublons où tous les attributs sont les mêmes. Ils sont rares car ils proviennent de la superposition de deux emprises de cartes marines avec une échelle très proche. Par contre ils peuvent aussi résulter d’une erreur de rechargement en double d’un fichier S57. Ces doublons peuvent être supprimés.
  • Des « faux » doublons où l’information de la couche se retrouve en double sans que les identifiants des enregistrements soient forcément identiques. Ils apparaissent quand des zones cartographiées à différentes échelles sont chargées dans la même base de données. Aussi, selon l’échelle une même information (par exemple une obstruction) peut être de géométrie différente (point sur carte, surface sur l’autre). Ce type de doublon ne doit pas être supprimé, mais géré.

Pour pouvoir gérer ces doublons, mais aussi l’affichage correct des informations, il est nécessaire d’ajouter des attributs de la carte aux couches. En effet, une fois intégrées dans une couche les entités de différents fichiers n’ont aucun attribut qui permet de remonter à leur source.

Nous avons inclus dans la procédure d’import SQL le code nécessaire qui permet d’ajouter à toutes les tables du schéma le nom du fichier, l’échelle de compilation des données, et la finalité de la carte marine.

Pour ce qui est du nom, il peut être utile dans la maintenance ultérieure de la base de données de pouvoir sélectionner les entités correspondantes à un fichier source S57.

Si le nom de la carte est d’une utilité relative, il n’en va pas de même de l’échelle, car c’est un critère indispensable dans la recherche de doublons. En effet, lors du mélange des entités en provenance de plusieurs fichiers S57 il y aura une coexistence plus ou moins heureuse de données issues de différentes échelles.

Outre l’échelle, il y a une information qui peut s’avérer très utile, la finalité (purpose) de la carte. C’est une valeur comprise entre 1 et 6 et qui correspond à l’objectif principal de la carte :

  • 1 : Vue d’ensemble
  • 2 : Généralités
  • 3 : Côtière
  • 4 : Approche
  • 5 : Port
  • 6 : Accostage

Dans la base de données du projet avec PostgreSQL/Postgis, nous avons importé 4500 fichiers S57.
Les valeurs min et max de l’échelle de toutes les cartes pour l’objectif 5 sont 3000 et 60000. Les valeurs min et max de l’échelle pour l’objectif 6 sont 2500 et 15000. On voit bien que les valeurs d’échelle des cartes les plus détaillées se retrouvent à l’intérieur des cartes de type 5.

Voici le résultat pour l’ensemble des finalités :

Tableau des finalités et des échelles correspondantes
Purpose min_scale max_scale
1 325000 10000000
2 100000 1534076
3 50000 600000
4 12500 150000
5 3000 60000
6 2500 15000

La table DSID des fichiers S57 contient deux attributs avec le nom du fichier S57 et l’échelle de compilation des données, ainsi que l’attribut ‘finalité’. Cet attribut se retrouve dans la même table DSID utilisée pour récupérer l’échelle avec le nom de DSID_INTU.

Comme les commandes ogr2ogr ne chargent, par défaut, que les tables spatiales, nous devrons exécuter une commande spéciale en demandant le chargement de la table DSID:

ogr2ogr -skipfailures -append -update -f PostgreSQL PG: »dbname…  » DSID

Import des « primitives »

Un fichier S57 a donc une série de tables contenant l’information géométrique, dénommées « primitives » :

  • IsolatedNode (points)
  • ConnectedNode (points)
  • Edge (polylignes)
  • Face (polygones)

La table attributaire des différents objets S57 contient seulement les attributs des objets.

Ce qui complique la tâche c’est qu’il y a deux attributs qui se réfèrent aux géométries : posacc (l’estimation de la précision de la position, valeur quantitative) et quapos (qualité de la position, variable qualitative).

Ces deux attributs se trouvent dans les tables des primitives.

Pour passer de la structure S57 à une structure SIG (shapefile, geopackage, postgis) nous utilisons la bibliothèque GDAL et sa commande ogr2ogr.

Cette commande va créer des tables SIG à partir de la structure S57, en créant une table par objet S57, en affectant à chaque entité les géométries correspondantes tirées des tables primitives et en ajoutant à chaque entité les attributs de l’objet S57. La trace des primitives utilisées pour la géométrie de chaque entité se trouve dans le champ NAME_RCID des tables SIG, à condition d’avoir ajouté les options -oo « RETURN_LINKAGES=ON » –oo « LNAM_REFS=ON » à la ligne de commande ogr2ogr.

La figure suivante montre une couche de type point. La valeur indiquée dans le champ NAME_RCID est celle RCID du point utilisé de la table IsolatedNode.

table de type point

La figure suivante montre un exemple de couche de type linéaire. Les valeurs indiquées dans le champ NAME_RCID sont celles des RCID des polylignes utilisées de la table Edge.

table de type polyligne

La figure suivante montre un exemple de couche de type polygone. Les valeurs indiquées dans le champ NAME_RCID sont celles des polylignes utilisées de la table Edge.

table de type polygone

Pour pouvoir récupérer les attributs QUAPOS et POSACC de chaque entité des tables de type point nous devons récupérer les valeurs du point IsolatedNode pour les affecter aux tables des différents objets ENC.

Si les identifiants étaient directement les RCID dans les tables ENC, on pourrait faire une jointure entre chaque table (soundg, obstrn,…) et IsolatedNode. Mais comme vous pouvez le voir dans les images précédentes, l’attribut NAME_RCID est de type stringlist ce qui bloque cette solution. Nous avons donc développé une requête SQL qui fait ce travail lors du chargement des données des schémas d’import vers le schéma ENC.

Les schémas PostgreSQL

Pour créer les tables d’import dans un schéma spécifique il faut utiliser l’option active_schema d’ogr2ogr. Avec cette option, PostgreSQL permet de créer des tables avec le même nom dans plusieurs schémas différents. Il n’y a qu’une seule exception, le schéma Public. Si un nom de table est utilisé dans ce schéma, l’option active_schema est ignorée. Il faut donc faire attention à ne pas créer des tables S57 dans le schéma Public. Si cela arrive, il faudra les effacer une à une manuellement.

Création avec une requête SQL

La requête suivante crée les quatre schémas nécessaires :

createschemas.sql

CREATE SCHEMA IF NOT EXISTS encm
AUTHORIZATION pg_database_owner;
GRANT ALL ON SCHEMA encm TO pg_database_owner;
CREATE SCHEMA IF NOT EXISTS pointsenc
AUTHORIZATION pg_database_owner;
GRANT ALL ON SCHEMA pointsenc TO pg_database_owner;
CREATE SCHEMA IF NOT EXISTS linesenc
AUTHORIZATION pg_database_owner;
GRANT ALL ON SCHEMA linesenc TO pg_database_owner;
CREATE SCHEMA IF NOT EXISTS polysenc
AUTHORIZATION pg_database_owner;
GRANT ALL ON SCHEMA polysenc TO pg_database_owner;

Création avec pgAdmin

Pour créer les schémas, ouvrez pgAdmin4, et sur Schemas ouvrez le menu contextuel->Create-Schema

ctreate schema pgadmin4

Entrez le nom souhaité pour le schéma:

create schema general

Répétez cette opération pour créer les quatre schémas nécessaires pour notre base de données ENC

postgresql schemas

ATTENTION! Les deux méthodes de création ne donnent pas le même résultat. Quand vous utilisez pgAdmin, le nom des schémas comporte des majuscules et minuscules et sera encadré par des guillemets (« PointsENC », par exemple). Quand vous utilisez le SQL, les noms seront toujours en minuscules et il n’y aura pas de guillemets (pointsenc par exemple).Pour éviter ceci, n’utilisez pas de majuscules dans pgAdmin.

Dans la suite de cet article nous utiliserons les noms issus de la requête SQL. Si vous optez par l’utilisation de majuscules, il faudra modifier les noms des schémas dans les codes fournis.

Préparation des schémas d’import

La phase d’import des tables avec ogr2ogr ne se limite pas à la simple exécution de la commande de transcodage S57->Postgresql.

Une fois le schéma alimenté par les tables des classes du fichier S57, nous allons ajouter la table DSID qui doit permettre de récupérer le nom du fichier S57, l’échelle de compilation des données et la finalité de la carte.

Au préalable, il faut ajouter ces attributs à toutes les tables non vides résultant de la commande ogr2ogr, en profitant déjà à créer aussi les attributs QUAPOS et POSACC qui seront remplis ultérieurement.

Le principe de cette étape est donc :

  1. Dans le fichier batch (.bat) on exécute la commande de chargement d’un type de géométrie.
  2. Une fois cette ligne de code exécutée, on charge dans le même schéma la table DSID
  3. Un trigger de type AFTER INSERT sur la table dsid du schéma commence par supprimer les tables vides, puis crée les attributs enc_chart, scale, purpose, posacc et quapos dans toutes les tables. Il ajoute dans tous les enregistrements des tables les valeurs de enc_chart,scale et purpose.

Cette procédure est faite pour chaque type de géométrie : point, ligne et polygone.

Pour que cette procédure fonctionne nous avons quelques éléments à mettre en place dans la base Postgresql.

Les tables DSID des schémas d’import

Étant donné qu’on utilisera un trigger sur ces tables, il faut les créer au préalable du premier chargement. On va créer donc, dans chaque schéma d’import une table

  • Pointsdsid dans le schéma pointsenc
  • Linesdsid dans le schéma linesenc
  • Polysdsid dans le schéma polysenc

create_DSID_tables.sql

-- Création de la séquence pointsdsid_ogc_fid_seq
CREATE SEQUENCE IF NOT EXISTS pointsenc.pointsdsid_ogc_fid_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;

-- Création de la séquence polysdsid_ogc_fid_seq

CREATE SEQUENCE IF NOT EXISTS polysenc.polysdsid_ogc_fid_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;

    -- Création de la séquence linesdsid_ogc_fid_seq

CREATE SEQUENCE IF NOT EXISTS linesenc.linesdsid_ogc_fid_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-- Table: pointsenc.pointsdsid

-- DROP TABLE IF EXISTS pointsenc.pointsdsid;

CREATE TABLE IF NOT EXISTS pointsenc.pointsdsid
(
ogc_fid integer NOT NULL DEFAULT nextval('pointsenc.pointsdsid_ogc_fid_seq'::regclass),
dsid_expp numeric(3,0),
dsid_intu numeric(3,0),
dsid_dsnm character varying COLLATE pg_catalog."default",
dsid_edtn character varying COLLATE pg_catalog."default",
dsid_updn character varying COLLATE pg_catalog."default",
dsid_uadt character varying(8) COLLATE pg_catalog."default",
dsid_isdt character varying(8) COLLATE pg_catalog."default",
dsid_sted numeric(11,6),
dsid_prsp numeric(3,0),
dsid_psdn character varying COLLATE pg_catalog."default",
dsid_pred character varying COLLATE pg_catalog."default",
dsid_prof numeric(3,0),
dsid_agen numeric(5,0),
dsid_comt character varying COLLATE pg_catalog."default",
dssi_dstr numeric(3,0),
dssi_aall numeric(3,0),
dssi_nall numeric(3,0),
dssi_nomr numeric(10,0),
dssi_nocr numeric(10,0),
dssi_nogr numeric(10,0),
dssi_nolr numeric(10,0),
dssi_noin numeric(10,0),
dssi_nocn numeric(10,0),
dssi_noed numeric(10,0),
dssi_nofa numeric(10,0),
dspm_hdat numeric(3,0),
dspm_vdat numeric(3,0),
dspm_sdat numeric(3,0),
dspm_cscl numeric(10,0),
dspm_duni numeric(3,0),
dspm_huni numeric(3,0),
dspm_puni numeric(3,0),
dspm_coun numeric(3,0),
dspm_comf numeric(10,0),
dspm_somf numeric(10,0),
dspm_comt character varying COLLATE pg_catalog."default",
CONSTRAINT pointsdsid_pkey PRIMARY KEY (ogc_fid)
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS pointsenc.pointsdsid
OWNER to postgres;
-- Table: polysenc.polysdsid

-- DROP TABLE IF EXISTS polysenc.polysdsid;

CREATE TABLE IF NOT EXISTS polysenc.polysdsid
(
ogc_fid integer NOT NULL DEFAULT nextval('polysenc.polysdsid_ogc_fid_seq'::regclass),
dsid_expp numeric(3,0),
dsid_intu numeric(3,0),
dsid_dsnm character varying COLLATE pg_catalog."default",
dsid_edtn character varying COLLATE pg_catalog."default",
dsid_updn character varying COLLATE pg_catalog."default",
dsid_uadt character varying(8) COLLATE pg_catalog."default",
dsid_isdt character varying(8) COLLATE pg_catalog."default",
dsid_sted numeric(11,6),
dsid_prsp numeric(3,0),
dsid_psdn character varying COLLATE pg_catalog."default",
dsid_pred character varying COLLATE pg_catalog."default",
dsid_prof numeric(3,0),
dsid_agen numeric(5,0),
dsid_comt character varying COLLATE pg_catalog."default",
dssi_dstr numeric(3,0),
dssi_aall numeric(3,0),
dssi_nall numeric(3,0),
dssi_nomr numeric(10,0),
dssi_nocr numeric(10,0),
dssi_nogr numeric(10,0),
dssi_nolr numeric(10,0),
dssi_noin numeric(10,0),
dssi_nocn numeric(10,0),
dssi_noed numeric(10,0),
dssi_nofa numeric(10,0),
dspm_hdat numeric(3,0),
dspm_vdat numeric(3,0),
dspm_sdat numeric(3,0),
dspm_cscl numeric(10,0),
dspm_duni numeric(3,0),
dspm_huni numeric(3,0),
dspm_puni numeric(3,0),
dspm_coun numeric(3,0),
dspm_comf numeric(10,0),
dspm_somf numeric(10,0),
dspm_comt character varying COLLATE pg_catalog."default",
CONSTRAINT polysdsid_pkey PRIMARY KEY (ogc_fid)
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS polysenc.polysdsid
OWNER to postgres;
-- Table: linesenc.linesdsid

-- DROP TABLE IF EXISTS linesenc.linesdsid;

CREATE TABLE IF NOT EXISTS linesenc.linesdsid
(
ogc_fid integer NOT NULL DEFAULT nextval('linesenc.linesdsid_ogc_fid_seq'::regclass),
dsid_expp numeric(3,0),
dsid_intu numeric(3,0),
dsid_dsnm character varying COLLATE pg_catalog."default",
dsid_edtn character varying COLLATE pg_catalog."default",
dsid_updn character varying COLLATE pg_catalog."default",
dsid_uadt character varying(8) COLLATE pg_catalog."default",
dsid_isdt character varying(8) COLLATE pg_catalog."default",
dsid_sted numeric(11,6),
dsid_prsp numeric(3,0),
dsid_psdn character varying COLLATE pg_catalog."default",
dsid_pred character varying COLLATE pg_catalog."default",
dsid_prof numeric(3,0),
dsid_agen numeric(5,0),
dsid_comt character varying COLLATE pg_catalog."default",
dssi_dstr numeric(3,0),
dssi_aall numeric(3,0),
dssi_nall numeric(3,0),
dssi_nomr numeric(10,0),
dssi_nocr numeric(10,0),
dssi_nogr numeric(10,0),
dssi_nolr numeric(10,0),
dssi_noin numeric(10,0),
dssi_nocn numeric(10,0),
dssi_noed numeric(10,0),
dssi_nofa numeric(10,0),
dspm_hdat numeric(3,0),
dspm_vdat numeric(3,0),
dspm_sdat numeric(3,0),
dspm_cscl numeric(10,0),
dspm_duni numeric(3,0),
dspm_huni numeric(3,0),
dspm_puni numeric(3,0),
dspm_coun numeric(3,0),
dspm_comf numeric(10,0),
dspm_somf numeric(10,0),
dspm_comt character varying COLLATE pg_catalog."default",
CONSTRAINT linesdsid_pkey PRIMARY KEY (ogc_fid)
)

TABLESPACE pg_default;

ALTER TABLE IF EXISTS linesenc.linesdsid
OWNER to postgres;

Mise en place des triggers AFTER INSERT

Ces triggers vont, après l’insertion d’une ligne dans la table DSID du schéma,

  • Effacer les tables  vides présentes dans le schéma,
  • vérifier si les champs supplémentaires existent déjà, si ce n’est pas le cas créer les 5 attributs ‘(enc_chart, scale, purpose,posacc et quapos),
  • ajouter les valeurs de l’enregistrement DSID aux attributs enc_chart, scale et purpose,
  • et finalement effacer l’enregistrement de la table DSID.

Il y a une fonction par type de géométrie,

  • create_fields_and_update_values_pointsenc()
  • create_fields_and_update_values_linesenc()
  • create_fields_and_update_values_polysenc()

puis une requête SQL de mise en place des triggers sur chacune des tables DSID (pointsDSID,linesDSID,polysDSID)

create_fields_and_update_values_pointsenc()

CREATE OR REPLACE FUNCTION create_fields_and_update_values_pointsenc()

RETURNS TRIGGER AS
$$
DECLARE
table_record RECORD;
tables_import RECORD;
enc_chart_value TEXT;
scale_value NUMERIC;
purpose_value NUMERIC;
empty_tables int;
BEGIN
--Le code suivant permet de supprimer les tables vides d'un schéma d'import:
FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'pointsenc' AND table_name != 'pointsdsid' LOOP
-- Composer une requête dynamique pour vérifier si la table est vide
EXECUTE format('SELECT COUNT(*) FROM pointsenc.%I', table_record.table_name) INTO empty_tables;

-- Si le nombre de lignes est égal à zéro, supprimer la table
    IF empty_tables = 0 THEN
        EXECUTE format('DROP TABLE IF EXISTS pointsenc.%I CASCADE',  table_record.table_name);
        RAISE NOTICE 'Table pointsenc.%I supprimée car elle est vide.',  table_record.table_name;
    END IF;
END LOOP;

-- Parcours de toutes les tables du schéma pointsenc 
FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'pointsenc' AND table_name != 'pointsdsid' LOOP
    -- Vérifie si les champs enc_chart et scale n'existent pas dans la table actuelle
    IF NOT EXISTS (
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'pointsenc' AND table_name = table_record.table_name AND column_name IN ('enc_chart', 'scale','purpose')
    ) THEN
        -- Crée le champ enc_chart de type texte
        EXECUTE format('ALTER TABLE pointsenc.%I ADD COLUMN enc_chart TEXT', table_record.table_name);
        -- Crée le champ scale de type numérique
        EXECUTE format('ALTER TABLE pointsenc.%I ADD COLUMN scale NUMERIC', table_record.table_name);
        -- Crée le champ purpose de type numérique
        EXECUTE format('ALTER TABLE pointsenc.%I ADD COLUMN purpose NUMERIC', table_record.table_name);
            IF NOT EXISTS (
                SELECT column_name FROM information_schema.columns
                WHERE table_schema = 'pointsenc' AND table_name = table_record.table_name AND column_name IN ('posacc','quapos')
                ) THEN
                -- Crée le champ POSACC de type numérique
                EXECUTE format('ALTER TABLE pointsenc.%I ADD COLUMN posacc NUMERIC(10,0)', table_record.table_name);
                -- Crée le champ QUAPOS de type numérique
                EXECUTE format('ALTER TABLE pointsenc.%I ADD COLUMN quapos INTEGER', table_record.table_name);
            END IF;
        RAISE NOTICE 'Champs enc_chart, scale , purpose, POSACC et QUIAPOS créés dans la table %', table_record.table_name;

    END IF;
        -- Obtient la valeur de enc_chart à partir de la table DSID pour DSID_DSNM
        SELECT DSID_DSNM INTO enc_chart_value FROM pointsdsid LIMIT 1;
        -- Obtient la valeur de scale à partir de la table DSID pour DSPM_CSCL
        SELECT DSPM_CSCL INTO scale_value FROM pointsdsid LIMIT 1;
        -- Obtient la valeur de purpose à partir de la table DSID pour DSID_INTU
        SELECT DSID_INTU INTO purpose_value FROM pointsdsid LIMIT 1;

        -- Met à jour les enregistrements avec les valeurs trouvées dans la table DSID
    EXECUTE format('UPDATE pointsenc.%I SET enc_chart = $1 WHERE enc_chart IS NULL', table_record.table_name) USING enc_chart_value;
    EXECUTE format('UPDATE pointsenc.%I SET scale = $1 WHERE scale IS NULL', table_record.table_name) USING scale_value;
    EXECUTE format('UPDATE pointsenc.%I SET purpose = $1 WHERE purpose IS NULL', table_record.table_name) USING purpose_value;


END LOOP;

-- Efface l'enregistrement de la table DSID
DELETE FROM pointsenc.pointsdsid;

RETURN NULL;

END;
$$
LANGUAGE plpgsql;

create_fields_and_update_values_linesenc()



CREATE OR REPLACE FUNCTION create_fields_and_update_values_linesenc()
RETURNS TRIGGER AS
$$
DECLARE
table_record RECORD;
tables_import RECORD;
enc_chart_value TEXT;
scale_value NUMERIC;
purpose_value NUMERIC;
empty_tables int;
BEGIN
--Le code suivant permet de supprimer les tables vides d'un schéma d'import:
FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'linesenc' AND table_name != 'linesdsid' LOOP
-- Composer une requête dynamique pour vérifier si la table est vide
EXECUTE format('SELECT COUNT(*) FROM linesenc.%I', table_record.table_name) INTO empty_tables;

-- Si le nombre de lignes est égal à zéro, supprimer la table
    IF empty_tables = 0 THEN
        EXECUTE format('DROP TABLE IF EXISTS linesenc.%I CASCADE',  table_record.table_name);
        RAISE NOTICE 'Table linesenc.%I supprimée car elle est vide.',  table_record.table_name;
    END IF;
END LOOP;

-- Parcours de toutes les tables du schéma linesenc 
FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'linesenc' AND table_name != 'linesdsid' LOOP
    -- Vérifie si les champs enc_chart et scale n'existent pas dans la table actuelle
    IF NOT EXISTS (
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'linesenc' AND table_name = table_record.table_name AND column_name IN ('enc_chart', 'scale','purpose')
    ) THEN
        -- Crée le champ enc_chart de type texte
        EXECUTE format('ALTER TABLE linesenc.%I ADD COLUMN enc_chart TEXT', table_record.table_name);
        -- Crée le champ scale de type numérique
        EXECUTE format('ALTER TABLE linesenc.%I ADD COLUMN scale NUMERIC', table_record.table_name);
        -- Crée le champ purpose de type numérique
        EXECUTE format('ALTER TABLE linesenc.%I ADD COLUMN purpose NUMERIC', table_record.table_name);
        RAISE NOTICE 'Champs enc_chart, scale et purpose créés dans la table %', table_record.table_name;
            IF NOT EXISTS (
            SELECT column_name FROM information_schema.columns
            WHERE table_schema = 'linesenc' AND table_name = table_record.table_name AND column_name IN ('posacc','quapos')
            ) THEN
            -- Crée le champ POSACC de type numérique
            EXECUTE format('ALTER TABLE linesenc.%I ADD COLUMN POSACC NUMERIC(10,0)', table_record.table_name);
            -- Crée le champ QUAPOS de type numérique
            EXECUTE format('ALTER TABLE linesenc.%I ADD COLUMN QUAPOS INTEGER', table_record.table_name);
        END IF;
    RAISE NOTICE 'Champs enc_chart, scale et purpose créés dans la table %', table_record.table_name;

    END IF;
        -- Obtient la valeur de enc_chart à partir de la table DSID pour DSID_DSNM
        SELECT DSID_DSNM INTO enc_chart_value FROM linesenc.linesdsid LIMIT 1;
        -- Obtient la valeur de scale à partir de la table DSID pour DSPM_CSCL
        SELECT DSPM_CSCL INTO scale_value FROM linesenc.linesdsid LIMIT 1;
        -- Obtient la valeur de purpose à partir de la table DSID pour DSID_INTU
        SELECT DSID_INTU INTO purpose_value FROM linesenc.linesdsid LIMIT 1;

        -- Met à jour les enregistrements avec les valeurs trouvées dans la table DSID
    EXECUTE format('UPDATE linesenc.%I SET enc_chart = $1 WHERE enc_chart IS NULL', table_record.table_name) USING enc_chart_value;
    EXECUTE format('UPDATE linesenc.%I SET scale = $1 WHERE scale IS NULL', table_record.table_name) USING scale_value;
    EXECUTE format('UPDATE linesenc.%I SET purpose = $1 WHERE purpose IS NULL', table_record.table_name) USING purpose_value;
END LOOP;

-- Efface l'enregistrement de la table DSID
DELETE FROM linesenc.linesdsid;

RETURN NULL;

END;
$$
LANGUAGE plpgsql;

create_fields_and_update_values_polysenc()

CREATE OR REPLACE FUNCTION create_fields_and_update_values_polysenc()
RETURNS TRIGGER AS
$$
DECLARE
table_record RECORD;
tables_import RECORD;
enc_chart_value TEXT;
scale_value NUMERIC;
purpose_value NUMERIC;
empty_tables int;
BEGIN
--Le code suivant permet de supprimer les tables vides d'un schéma d'import:
FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'polysenc' AND table_name != 'polysdsid' LOOP
-- Composer une requête dynamique pour vérifier si la table est vide
EXECUTE format('SELECT COUNT(*) FROM polysenc.%I', table_record.table_name) INTO empty_tables;

-- Si le nombre de lignes est égal à zéro, supprimer la table
    IF empty_tables = 0 THEN
        EXECUTE format('DROP TABLE IF EXISTS polysenc.%I CASCADE',  table_record.table_name);
        RAISE NOTICE 'Table polysenc.%I supprimée car elle est vide.',  table_record.table_name;
    END IF;
END LOOP;

-- Parcours de toutes les tables du schéma polysenc 
FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'polysenc' AND table_name != 'polysdsid' LOOP
    -- Vérifie si les champs enc_chart et scale n'existent pas dans la table actuelle
    IF NOT EXISTS (
        SELECT column_name FROM information_schema.columns
        WHERE table_schema = 'polysenc' AND table_name = table_record.table_name AND column_name IN ('enc_chart', 'scale','purpose')
    ) THEN
        -- Crée le champ enc_chart de type texte
        EXECUTE format('ALTER TABLE polysenc.%I ADD COLUMN enc_chart TEXT', table_record.table_name);
        -- Crée le champ scale de type numérique
        EXECUTE format('ALTER TABLE polysenc.%I ADD COLUMN scale NUMERIC', table_record.table_name);
        -- Crée le champ purpose de type numérique
        EXECUTE format('ALTER TABLE polysenc.%I ADD COLUMN purpose NUMERIC', table_record.table_name);
                    IF NOT EXISTS (
                SELECT column_name FROM information_schema.columns
                WHERE table_schema = 'polysenc' AND table_name = table_record.table_name AND column_name IN ('posacc','quapos')
                ) THEN
                -- Crée le champ POSACC de type numérique
                EXECUTE format('ALTER TABLE polysenc.%I ADD COLUMN POSACC NUMERIC(10,0)', table_record.table_name);
                -- Crée le champ QUAPOS de type numérique
                EXECUTE format('ALTER TABLE polysenc.%I ADD COLUMN QUAPOS INTEGER', table_record.table_name);
            END IF;
        RAISE NOTICE 'Champs enc_chart, scale et purpose créés dans la table %', table_record.table_name;

    END IF;
        -- Obtient la valeur de enc_chart à partir de la table DSID pour DSID_DSNM
        SELECT DSID_DSNM INTO enc_chart_value FROM polysenc.polysdsid LIMIT 1;
        -- Obtient la valeur de scale à partir de la table DSID pour DSPM_CSCL
        SELECT DSPM_CSCL INTO scale_value FROM polysenc.polysdsid LIMIT 1;
        -- Obtient la valeur de purpose à partir de la table DSID pour DSID_INTU
        SELECT DSID_INTU INTO purpose_value FROM polysenc.polysdsid LIMIT 1;

        -- Met à jour les enregistrements avec les valeurs trouvées dans la table DSID
    EXECUTE format('UPDATE polysenc.%I SET enc_chart = $1 WHERE enc_chart IS NULL', table_record.table_name) USING enc_chart_value;
    EXECUTE format('UPDATE polysenc.%I SET scale = $1 WHERE scale IS NULL', table_record.table_name) USING scale_value;
    EXECUTE format('UPDATE polysenc.%I SET purpose = $1 WHERE purpose IS NULL', table_record.table_name) USING purpose_value;
END LOOP;

-- Efface l'enregistrement de la table DSID
DELETE FROM polysenc.polysdsid;

RETURN NULL;

END;
$$
LANGUAGE plpgsql;

createtriggersfields()

CREATE OR REPLACE TRIGGER check_update
AFTER INSERT ON linesenc.linesdsid
FOR EACH ROW
EXECUTE PROCEDURE create_fields_and_update_values_linesenc();

CREATE OR REPLACE TRIGGER check_update
AFTER INSERT ON polysenc.polysdsid
FOR EACH ROW
EXECUTE PROCEDURE create_fields_and_update_values_polysenc();

CREATE OR REPLACE TRIGGER check_update
AFTER INSERT ON pointsenc.pointsdsid
FOR EACH ROW
EXECUTE PROCEDURE create_fields_and_update_values_pointsenc();

Workflow pour le chargement des fichiers S57

Commandes ogr2ogr pour créer les tables Postgis

Fort de tous ces éléments, voici donc le fichier .bat avec les lignes de commandes ogr2ogr pour créer les tables dans les schémas d’import:

Commandes ogr2ogr



@echo off
setlocal enabledelayedexpansion

REM Vérifie qu’un répertoire a été fourni
if « %~1″== » » (
echo Usage: %0 directory000
exit /b 1
)

REM Récupère l’argument
set « directory=%~1 »

REM Itère sur tous les fichiers .000 dans le répertoire
for /r « %directory% » %%i in (*.000) do (
echo Traitement du fichier: %%i

ogr2ogr -skipfailures -append -update -s_srs EPSG:4326 -t_srs EPSG:4326 ^
    -where "OGR_GEOMETRY='POINT' or OGR_GEOMETRY='MULTIPOINT'" ^
    -oo RETURN_PRIMITIVES=ON -oo SPLIT_MULTIPOINT=ON -oo RETURN_LINKAGES=ON -oo LNAM_REFS=ON -oo ADD_SOUNDG_DEPTH=ON ^
    -nlt MULTIPOINT -f PostgreSQL ^
    PG:"dbname=postgis_34_sample host=localhost port=5432 user=postgres password=1touria+ active_schema=pointsenc" %%i

ogr2ogr -skipfailures -append -update -nln pointsDSID -f PostgreSQL  PG:"dbname=postgis_34_sample host=localhost port=5432 user=postgres password=1touria+ active_schema=pointsenc" %%i DSID

ogr2ogr -skipfailures -append -update -s_srs EPSG:4326 -t_srs EPSG:4326 ^
    -where "OGR_GEOMETRY='LINESTRING' or OGR_GEOMETRY='MULTILINESTRING'" ^
    -oo RETURN_PRIMITIVES=ON -oo SPLIT_MULTIPOINT=ON -oo RETURN_LINKAGES=ON -oo LNAM_REFS=ON ^
    -f PostgreSQL PG:"dbname=postgis_34_sample host=localhost port=5432 user=postgres password=1touria+ active_schema=linesenc" %%i

ogr2ogr -skipfailures -append -update -nln linesDSID -f PostgreSQL ^
    PG:"dbname=postgis_34_sample host=localhost port=5432 user=postgres password=1touria+ active_schema=linesenc" %%i DSID

ogr2ogr -skipfailures -append -update -s_srs EPSG:4326 -t_srs EPSG:4326 ^
    -where "OGR_GEOMETRY='POLYGON' or OGR_GEOMETRY='MULTIPOLYGON'" ^
    -oo RETURN_PRIMITIVES=ON -oo SPLIT_MULTIPOINT=ON -oo RETURN_LINKAGES=ON -oo LNAM_REFS=ON ^
    -f PostgreSQL PG:"dbname=postgis_34_sample host=localhost port=5432 user=postgres password=1touria+ active_schema=polysenc" %%i

ogr2ogr -skipfailures -append -update -nln polysDSID -f PostgreSQL ^
    PG:"dbname=postgis_34_sample host=localhost port=5432 user=postgres password=1touria+ active_schema=polysenc" %%i DSID

)

echo Traitement terminé.
pause

Vous devez modifier les informations de connexion à votre base de données PostgreSQL/POstgis :

PostgreSQL PG: »dbname=’postgis_34_sample’ host=’localhost’ port=’5434′ user=’postgres’ password=’xxxxxx’

Pour exécuter ces lignes de commande il suffit d’ouvrir la fenêtre de shell d’OSGeo4W:

OSGeo4W shell

La fenêtre de Shell s’ouvre

osgeo4W shell window

Rentrez alors la ligne de commande suivante :

.\Path/ mass_load_s57_postgis.bat  repertoire_enc

Repertoire_enc est le répertoire contenant les fichiers .000 des cartes enc. Tous les fichiers .000 de ce répertoire seront chargés dans les schémas d’import.

On aura alors comme résultat une série de tables créées dans chaque schéma d’import. Par contre il y aura des tables complètement vides. En effet, si le type de géométrie est possible pour une classe d’objet, la table sera créée mais s’il n’y a aucune occurrence dans le fichier S57 traité, la table n’aura aucun enregistrement.

Chargement de la base de données à partir des schémas d’import

La fonction clone_tables_with_prefix charge la base de données ENC avec les tables des trois schémas d’import.

  • Tout d’abord elle efface de chaque schéma d’import les tables vides, créées par ogr2ogr dans le cas où un type de géométrie prévu n’a pas été utilisé dans le fichier .000.
  • Deuxièmement, pour chaque schéma d’import elle vérifie si la table du schéma d’import existe déjà dans la base de données ENC. Si elle n’existe pas, elle créée la table avec le préfixe correspondant au type de géométrie (pt_, li_, pl_).
  • La fonction ajoute les enregistrements de la table d’import dans la table ENC.
  • Pour les tables de type point, elle met à jour les attributs posacc et quapos de la table à partir des valeurs de la table IsolatedNode.
  • Pour les tables de type ligne et polygone, elle met à jour les attributs posacc et quapos de la table à partir des valeurs de la table Edge.
  • Finalement la fonction vide toutes les tables des schémas d’importt, les laissant alors prêts pour un nouveau chargement avec mes commandes ogr2ogr.

Au préalable d’utiliser cette fonction il faut installer la fonction delete_all_records_in_schema :

Copiez la requête dans une fenêtre SQL de pgAdmin et exécutez-la.

delete_all_records_in_schema 

-- FUNCTION: public.delete_all_records_in_schema(text)

-- DROP FUNCTION IF EXISTS public.delete_all_records_in_schema(text);

CREATE OR REPLACE FUNCTION public.delete_all_records_in_schema(
schema_name text)
RETURNS void
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
table_record RECORD;
BEGIN
-- Récupérer toutes les tables du schéma spécifié
FOR table_record IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema = schema_name AND table_type = 'BASE TABLE'
LOOP
-- Construction de la requête DELETE pour chaque table
EXECUTE format('DELETE FROM %I.%I', schema_name, table_record.table_name);
END LOOP;
END;
$BODY$;

ALTER FUNCTION public.delete_all_records_in_schema(text)
OWNER TO postgres;

La mise à jour de la base ENC se fait en appelant la commande

SELECT clone_tables_with_prefix()

N’oubliez pas de remplacer le nom du schéma (ci après enc2) par le nom de votre schéma enc.

clone_table_with_prefix

CREATE OR REPLACE FUNCTION clone_tables_with_prefix()
RETURNS void AS
$$
DECLARE
table_nom text;
BEGIN
-- Clonage des tables dans le schéma ENC et mise à jour des tables existantes

-- Boucle sur les tables du schéma pointsENC
FOR table_nom IN (SELECT table_name as table_nom FROM information_schema.tables WHERE table_schema = 'pointsenc' AND table_name NOT IN ('pointsdsid','isolatednode','connectednode'))
LOOP
    -- Construction de la requête dynamique pour créer ou mettre à jour la table dans ENC
    EXECUTE format('CREATE TABLE IF NOT EXISTS enc2.pt_%I AS SELECT * FROM pointsenc.%I', table_nom, table_nom);
    EXECUTE format('INSERT INTO enc2.pt_%I SELECT * FROM pointsenc.%I ON CONFLICT DO NOTHING', table_nom, table_nom);
    EXECUTE format('UPDATE enc2.pt_%I SET posacc = isolatednode.posacc,  quapos = isolatednode.quapos FROM pointsenc.IsolatedNode isolatednode WHERE enc2.pt_%I.NAME_RCID[1] = isolatednode.RCID   AND enc2.pt_%I.enc_chart = isolatednode.enc_chart;', table_nom, table_nom,table_nom);

END LOOP;

-- Boucle sur les tables du schéma LinesENC
FOR table_nom IN (SELECT table_name as table_nom FROM information_schema.tables WHERE table_schema = 'linesenc' AND table_name NOT IN ('linesdsid','edge'))
LOOP
    -- Construction de la requête dynamique pour créer ou mettre à jour la table dans ENC
    EXECUTE format('CREATE TABLE IF NOT EXISTS enc2.li_%I AS SELECT * FROM linesenc.%I', table_nom, table_nom);
    EXECUTE format('INSERT INTO enc2.li_%I SELECT * FROM linesenc.%I ON CONFLICT DO NOTHING', table_nom, table_nom);
    EXECUTE format('UPDATE enc2.li_%I SET posacc = edge.posacc,  quapos = edge.quapos FROM linesenc.edge edge WHERE enc2.li_%I.NAME_RCID[1] = edge.RCID   AND enc2.li_%I.enc_chart = edge.enc_chart;', table_nom, table_nom,table_nom);

END LOOP;

-- Boucle sur les tables du schéma PolysENC
FOR table_nom IN (SELECT table_name as table_nom FROM information_schema.tables WHERE table_schema = 'polysenc' AND table_name NOT IN ( 'polysdsid','m_qual','m_srel'))
LOOP
    -- Construction de la requête dynamique pour créer ou mettre à jour la table dans ENC
    EXECUTE format('CREATE TABLE IF NOT EXISTS enc2.pl_%I AS SELECT * FROM polysenc.%I', table_nom, table_nom);
    EXECUTE format('INSERT INTO enc2.pl_%I SELECT * FROM polysenc.%I ON CONFLICT DO NOTHING', table_nom, table_nom);
    EXECUTE format('UPDATE enc2.pl_%I SET posacc = edge.posacc,  quapos = edge.quapos FROM linesenc.edge edge WHERE enc2.pl_%I.NAME_RCID[1] = edge.RCID   AND enc2.pl_%I.enc_chart = edge.enc_chart;', table_nom, table_nom,table_nom);

END LOOP;
EXECUTE (SELECT delete_all_records_in_schema('pointsenc'));
EXECUTE (SELECT delete_all_records_in_schema('linesenc'));
EXECUTE (SELECT delete_all_records_in_schema('polysenc'));

EXECUTE (SELECT update_sbdare());
END;
$$ LANGUAGE plpgsql;

Traitement particulier de la table pt_SBDARE

Après la première exécution du script précédent vous devez, si les fichiers chargés avaient des valeurs pour les natures du fond, avoir dans le schéma ENC une table pt_sbdare. C’est la seule table qui nécessite un traitement particulier pour la symbologie par défaut que nous fournissons. En effet le traitement des valeurs des deux attributs nécessaires à créer l’étiquette de la nature du fond (NATSUR et NATQUA) est très complexe de par la nature des attributs (des StringLists) et des innombrables combinaisons possibles.

La solution appliquée ici est la suivante :

  • Une table natsurf liste les combinaisons de valeurs possibles des tuples natqua et natsur avec l’étiquette correspondante.
  • Une fonction update_sbdare traite les deux stringlists pour composer les tuples de valeurs et concatène de manière appropriée les étiquettes issues de la table natsurf.
  • La fonction met à jour les enregistrements de la table pt_sbdare dont la valeur de ‘label’ est nulle.

Au premier chargement des schémas d’import la table pt_sbdare n’existe pas. Une fois créée par un import, on peut définir un trigger qui exécutera la fonction automatiquement par la suite.

Vous devez donc :

  • Importer la table natsurf dans le schéma ENC
  • Créer la fonction update_sbdare
  • Exécuter la fonction manuellement pour la première fois

.

Import de la table natsurf

Chargez la requête suivante dans une fenêtre SQL de pgAdmin et exécutez-la. On considère que vous avez créé un schéma ‘enc’ pour votre base de données. Si ce n’est pas le cas, éditez la table en remplaçant ‘enc.natsurf’ par ‘votre_schéma.natsurf’.

natsurf.sql 

SET standard_conforming_strings = ON;
DROP TABLE IF EXISTS enc.natsurf CASCADE;
BEGIN;
CREATE TABLE enc.natsurf();
ALTER TABLE enc.natsurf ADD COLUMN "ogc_fid" SERIAL CONSTRAINT "natsurf_pk" PRIMARY KEY;
ALTER TABLE enc.natsurf ADD COLUMN "fid" NUMERIC(20,0);
ALTER TABLE enc.natsurf ADD COLUMN "natsurt" VARCHAR;
ALTER TABLE enc.natsurf ADD COLUMN "natquat" VARCHAR;
ALTER TABLE enc.natsurf ADD COLUMN "etiq" VARCHAR;
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (1, '1', '0', 'M');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (2, '1', '1', 'fM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (3, '1', '2', 'mM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (4, '1', '3', 'cM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (5, '1', '4', 'bkM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (6, '1', '5', 'syM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (7, '1', '6', 'soM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (8, '1', '7', 'sfM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (9, '1', '8', 'vM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (10, '1', '9', 'caM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (11, '1', '10', 'hM');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (12, '2', '0', 'Cy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (13, '2', '1', 'fCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (14, '2', '2', 'mCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (15, '2', '3', 'cCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (16, '2', '4', 'bkCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (17, '2', '5', 'syCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (18, '2', '6', 'soCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (19, '2', '7', 'sfCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (20, '2', '8', 'vCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (21, '2', '9', 'caCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (22, '2', '10', 'hCy');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (23, '3', '0', 'Si');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (24, '3', '1', 'fSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (25, '3', '2', 'mSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (26, '3', '3', 'cSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (27, '3', '4', 'bkSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (28, '3', '5', 'sySi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (29, '3', '6', 'soSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (30, '3', '7', 'sfSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (31, '3', '8', 'vSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (32, '3', '9', 'caSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (33, '3', '10', 'hSi');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (34, '4', '0', 'S');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (35, '4', '1', 'fS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (36, '4', '2', 'mS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (37, '4', '3', 'cS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (38, '4', '4', 'bkS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (39, '4', '5', 'syS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (40, '4', '6', 'soS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (41, '4', '7', 'sfS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (42, '4', '8', 'vS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (43, '4', '9', 'caS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (44, '4', '10', 'hS');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (45, '5', '0', 'St');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (46, '5', '1', 'fSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (47, '5', '2', 'mSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (48, '5', '3', 'cSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (49, '5', '4', 'bkSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (50, '5', '5', 'sySt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (51, '5', '6', 'soSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (52, '5', '7', 'sfSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (53, '5', '8', 'vSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (54, '5', '9', 'caSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (55, '5', '10', 'hSt');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (56, '6', '0', 'G');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (57, '6', '1', 'fG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (58, '6', '2', 'mG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (59, '6', '3', 'cG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (60, '6', '4', 'bkG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (61, '6', '5', 'syG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (62, '6', '6', 'soG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (63, '6', '7', 'sfG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (64, '6', '8', 'vG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (65, '6', '9', 'caG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (66, '6', '10', 'hG');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (67, '7', '0', 'P');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (68, '7', '1', 'fP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (69, '7', '2', 'mP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (70, '7', '3', 'cP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (71, '7', '4', 'bkP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (72, '7', '5', 'syP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (73, '7', '6', 'soP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (74, '7', '7', 'sfP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (75, '7', '8', 'vP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (76, '7', '9', 'caP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (77, '7', '10', 'hP');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (78, '8', '0', 'Cb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (79, '8', '1', 'fCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (80, '8', '2', 'mCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (81, '8', '3', 'cCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (82, '8', '4', 'bkCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (83, '8', '5', 'syCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (84, '8', '6', 'soCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (85, '8', '7', 'sfCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (86, '8', '8', 'vCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (87, '8', '9', 'caCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (88, '8', '10', 'hCb');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (89, '9', '0', 'R');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (90, '9', '1', 'fR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (91, '9', '2', 'mR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (92, '9', '3', 'cR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (93, '9', '4', 'bkR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (94, '9', '5', 'syR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (95, '9', '6', 'soR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (96, '9', '7', 'sfR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (97, '9', '8', 'vR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (98, '9', '9', 'caR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (99, '9', '10', 'hR');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (100, '11', '0', 'L');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (101, '11', '1', 'fL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (102, '11', '2', 'mL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (103, '11', '3', 'cL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (104, '11', '4', 'bkL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (105, '11', '5', 'syL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (106, '11', '6', 'soL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (107, '11', '7', 'sfL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (108, '11', '8', 'vL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (109, '11', '9', 'caL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (110, '11', '10', 'hL');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (111, '14', '0', 'Co');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (112, '14', '1', 'fCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (113, '14', '2', 'mCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (114, '14', '3', 'cCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (115, '14', '4', 'bkCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (116, '14', '5', 'syCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (117, '14', '6', 'soCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (118, '14', '7', 'sfCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (119, '14', '8', 'vCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (120, '14', '9', 'caCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (121, '14', '10', 'hCo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (122, '17', '0', 'Sh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (123, '17', '1', 'fSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (124, '17', '2', 'mSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (125, '17', '3', 'cSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (126, '17', '4', 'bkSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (127, '17', '5', 'sySh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (128, '17', '6', 'soSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (129, '17', '7', 'sfSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (130, '17', '8', 'vSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (131, '17', '9', 'caSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (132, '17', '10', 'hSh');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (133, '18', '0', 'Bo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (134, '18', '1', 'fBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (135, '18', '2', 'mBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (136, '18', '3', 'cBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (137, '18', '4', 'bkBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (138, '18', '5', 'syBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (139, '18', '6', 'soBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (140, '18', '7', 'sfBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (141, '18', '8', 'vBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (142, '18', '9', 'caBo');
INSERT INTO enc.natsurf ("fid", "natsurt", "natquat", "etiq") VALUES (143, '18', '10', 'hBo');
COMMIT;

Création de la fonction update_sbdare

Chargez la requête suivante dans une fenêtrte SQL de pgAdmin et exécutez-la. On considère que vous avez créé un schéma ‘enc’ pour votre base de données. Si ce n’est pas le cas, éditez la table en remplaçant ‘enc.’ par ‘votre_schéma’.

update_sbdare.sql



CREATE OR REPLACE FUNCTION update_sbdare()
RETURNS VOID AS
$$
DECLARE
rec_row RECORD;
natsurt VARCHAR[4];
natquat VARCHAR[4];
S VARCHAR[3];
flag INT := 0;
etiq VARCHAR(25);
etiquet VARCHAR(25);
BEGIN
-- Vérifier si le champ 'Label' existe déjà
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'enc2' AND table_name = 'pt_sbdare' AND column_name = 'label'
) THEN

-- Parcourir les lignes de la table enc.pt_sbdare
FOR rec_row IN SELECT * FROM enc2.pt_sbdare WHERE label IS NULL LOOP
    -- Réinitialiser les variables à chaque itération de la boucle
    natsurt := ARRAY['','','',''];
    S := ARRAY[',',',',','];
    flag :=0;

    -- Extraire les parties de natsur
    FOR i IN 1..4 LOOP
        --sortie anticipée
        IF i=4 AND flag=1 THEN
            EXIT;
        END IF;

        -- Vérifier si rec_row.natsur[i] est NULL
        IF rec_row.natsur[i] IS NULL THEN
            IF flag=0 THEN
                natsurt[i] := '0';
            ELSE
                natsurt[i+1] := '0';
            END IF;
        -- Vérifier si rec_row.natsur[i] contient un '/'
        ELSIF strpos(rec_row.natsur[i], '/') = 0 THEN
            IF flag=0 THEN
                natsurt[i] := rec_row.natsur[i];
                IF rec_row.natqua[i] IS NOT NULL THEN
                    natquat[i] := rec_row.natqua[i];
                ELSE
                    natquat[i] := '0';
                END IF;
            ELSE
                natsurt[i+1] := rec_row.natsur[i];
                IF rec_row.natqua[i] IS NOT NULL THEN
                    natquat[i+1] := rec_row.natqua[i];
                ELSE
                    natquat[i] := '0';
                END IF;
            END IF;

        ELSE
            -- Extraire les parties avant et après le '/'
            IF i < 5 THEN
                natsurt[i] := split_part(rec_row.natsur[i], '/', 1);
                natsurt[i+1] := split_part(rec_row.natsur[i], '/', 2);
                IF rec_row.natqua[i] IS NOT NULL THEN
                    natquat[i] := rec_row.natqua[i];
                ELSE
                    natquat[i] := '0';
                END IF;
                S[i] := '/';
                flag :=1; -- nous avons trouvé une valeur avec un '/'
            ELSE
                natsurt[i] := split_part(rec_row.natsur[i], '/', 1);
            END IF;
        END IF;
    END LOOP;

    etiquet :='';
    etiq :='';

    FOR i IN 1..4 LOOP
        IF natsurt[i] <> '0' THEN
            -- Exécutez la requête SQL pour récupérer le label en fonction de natsurt[i] et natquat[i]
            EXECUTE 'SELECT etiq FROM enc2.natsurf WHERE NATSURT = $1 AND NATQUAT = $2' INTO etiq USING natsurt[i], natquat[i];

            IF i =1 THEN
                etiquet := etiq ;
            ELSE
                etiquet := etiquet || S[i-1] || etiq;
            END IF;
        END IF;
    END LOOP;

    -- Mettre à jour la ligne avec les valeurs extraites
    UPDATE enc2.pt_sbdare
    SET
        label = etiquet
    WHERE pt_sbdare.ogc_fid = rec_row.ogc_fid;
END LOOP;

END IF;
END;
$$
LANGUAGE plpgsql;

Exécution manuelle de la fonction pour la première mise à jour

Dans une fenêtre SQL de pgAdmin rentrez la requête

ALTER TABLE enc.pt_sbdare ADD COLUMN label VARCHAR(25);

SELECT update_sbdare()

Vous aurez comme résultat l’attribut ‘label’ renseigné dans la table pt_sbdare. Par la suite, lors de l’exécution de clone_tables_with_prefix() la mise à jour se fera automatiquement.

Si cet article vous a intéressé et que vous pensez qu'il pourrait bénéficier à d'autres personnes, n'hésitez pas à le partager sur vos réseaux sociaux en utilisant les boutons ci-dessous. Votre partage est apprécié !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *