diff --git a/docs/import_data.md b/docs/import_data.md index b9764c2..ef34665 100644 --- a/docs/import_data.md +++ b/docs/import_data.md @@ -1,64 +1,34 @@ # Importer des données -Pour la formation, on doit importer des données pour pouvoir travailler. QGIS possède plusieurs outils pour réaliser cette importation dans PostgreSQL. +Pour la formation, on doit **importer des données** pour pouvoir travailler. ## Import d'une couche depuis QGIS -On doit **charger au préalable la couche source** dans QGIS (SHP, TAB, etc.), puis on doit vérifier : +On doit **charger au préalable la couche source** dans QGIS (SHP, TAB, etc.), puis on doit **vérifier** : -* la **projection**, idéalement EPSG:2154 -* l'**encodage** : UTF-8, ISO-8859-15 ? Il faut ouvrir la table attributaire, et vérifier si les accents sont bien affichés. Sinon choisir le bon encodage dans l'onglet **Général** des **propriétés de la couche** +* la **projection**, idéalement `EPSG:2154` +* l'**encodage** : `UTF-8`, `ISO-8859-15`, etc. Il faut ouvrir la **table attributaire**, et vérifier si les accents sont bien affichés. Sinon choisir le bon encodage dans l'onglet **Général** des **propriétés de la couche** * les **champs**: noms, type, contenu -Pour importer, on utilise le bouton **Import de couche/fichier** du gestionnaire de bdd. On choisit par exemple le fichier des communes: +Pour importer, il existe plusieurs manières dans QGIS. La plus **performante** pour des gros volumes de données est l'utilisation de l'algorithme de la `boîte à outils` du menu `Traitement` appelé `Exporter vers PostgreSQL (Connexions disponibles`. -* on clique sur **Mettre à jour les options** -* on choisit le **nom** de la couche et le schéma **z_formation** -* on coche bien les 2 cases du bas pour **convertir les noms de champ en minuscule** (Convert fieldnames to lowercase) et pour **créer l'index spatial** +![Exporter vers PostgreSQL](media/qgis_traitement_exporter_postgresql_ogr.png) -Après l'import, on peut cliquer, dans le panneau de gauche, sur le nom de la couche créée et parcourir les données avec l'onglet **Table**. Si on souhaite comparer avec la couche d'origine, il suffit de charger la table, en double-cliquant dessus dans l'arbre (ou via les autres outils de QGIS) - -**NB**: si un champ s'appelle déjà id dans la donnée source, et qu'il contient des valeurs dupliquées, ou des valeurs textuelles, alors il faut cocher la case **Clé primaire** dans l'outil d'import, puis choisir un nom différent pour que QGIS crée ce nouvel identifiant dans le bon format (entier auto-incrémenté via une séquence, qu'on appelle aussi serial). Par ex: id_commune - -## Réimporter une donnée dans une table existante. - -### Avec suppression de la table puis recréation. - -Il suffit d'utiliser le même **outil d'import** via le gestionnaire de bdd, et cocher la case **Remplacer la table de destination si existante**. - -Attention, cela supprime la table avant de la recréer et de la remplir, ce qui peut entraîner des effets de bord (par exemple, on perd les droits définis) - -### Avec vidage puis ajout des nouvelles données - -Imaginons qu'on ait donné tous les droits sur les tables du schéma, par exemple via cette requête - -```sql --- Ajout des droits un schéma et sur toutes les tables d'un schéma -GRANT ALL ON SCHEMA z_formation TO "unutilisateur"; -GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA z_formation TO "unutilisateur"; -GRANT ALL ON SCHEMA z_formation TO "unepersonne"; -GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA z_formation TO "unepersonne"; -``` - -Ensuite, on souhaite réimporter le SHP, **sans perdre les droits**: on doit d'abord **vider la table** puis **réimporter les données**, sans cocher la case *Remplacer la table de destination si existante* - -```sql --- Vider une table en remettant à zéro la séquence --- qui permet d'auto-incrémenter le champ id (la clé primaire) -TRUNCATE TABLE z_formation.commune RESTART IDENTITY; -``` - -Ensuite, on importe via l'outil spécifique du menu **Traitement / Boîte à outils**. Chercher "export" dans le champ du haut (Rechercher...), et lancer l'algorithme **Exporter vers PostgreSQL (connexions disponibles)** de **GDAL**. Il faut choisir les options suivantes: +Pour trouver cet algorithme, chercher `PosgreSQL` dans le champ du haut, et lancer l'algorithme **Exporter vers PostgreSQL (connexions disponibles)** de **GDAL**. Il faut choisir les options suivantes : * choisir la bonne **connexion**, la couche en entrée, etc. -* choisir le **schéma**, par exemple z_formation -* choisir le **nom de la table**, par exemple commune -* laisser id dans le champ **Clef primaire** ou choisir le champ approprié -* décocher **Écraser la table existante** -* cocher **Ajouter à la table existante** +* choisir le **schéma**, par exemple `z_formation` +* choisir le **nom de la table**, par exemple `commune` +* laisser `id` dans le champ **Clef primaire** si aucun champ entier auto-incrémenté existe, ou choisir le champ approprié +* décocher **Convertir en morceaux multiples** pour les couches de points (et aussi pour les lignes et polygones si on est sûr) * laisser le reste par défaut. -Lancer l'algorithme, et vérifier une fois les données importées que les nouvelles données ont bien été ajoutées à la table. +![Algorithe d'export vers PostgreSQL](media/qgis_traitement_exporter_dialogue_algorithme.png) + +Après l'import, on peut charger la table comme une couche via **l'explorateur de QGIS** : + +* **rafraîchir** le contenu du schéma via clic-droit et `Rafraîchir` +* **double-cliquer** sur la table ## Importer plusieurs couches en batch @@ -68,4 +38,4 @@ Vous pouvez créer manuellement chaque ligne, ou choisir directement les couches https://docs.qgis.org/latest/fr/docs/user_manual/processing/batch.html -Continuer vers [Sélectionner des données: SELECT](./sql_select.md) +Continuer vers [Sélectionner des données : SELECT](./sql_select.md) diff --git a/docs/links_and_data.md b/docs/links_and_data.md index ea62ae9..280084a 100644 --- a/docs/links_and_data.md +++ b/docs/links_and_data.md @@ -11,31 +11,31 @@ Documentation des fonctions PostGIS: ## Base de données -Nous présupposons qu'une **base de données** est accessible pour la formation, via un utilisateur PostgreSQL avec des droits élevés (notamment pour créer des schémas et des tables). L'extension **PostGIS** doit aussi être activée sur cette base de données. +Nous présupposons qu'une **base de données** est accessible pour la formation, via un **rôle PostgreSQL** avec des droits élevés (notamment pour créer des schémas et des tables). L'extension **PostGIS** doit aussi être activée sur cette base de données. ## Jeux de données Pour cette formation, nous utilisons des données libres de droit : -* Un dump est téléchargable en cliquant sur ce [lien](https://github.com/3liz/formation-postgis/releases/download/1.0/data_formation.dump). +* Un dump est téléchargeable en cliquant sur ce [lien](https://github.com/3liz/formation-postgis/releases/download/1.0/data_formation.dump). -Il peut est chargé en base avec cette commande : `pg_restore -d "NOM_BASE" data_formation.dump` +Il peut est chargé en base avec cette commande : +```bash +pg_restore -h URL_SERVEUR -p 5432 -U NOM_UTILISATEUR -d NOM_BASE --no-owner --no-acl data_formation.dump +``` Ce jeu de données a pour sources : -* Extraction de données d'**OpenStreetMap** dans un format SIG, sous licence ODBL ( site https://github.com/igeofr/osm2igeo ). On utilisera par exemple les données de l'ancienne région Haute-Normandie: -https://www.data.data-wax.com/OSM2IGEO/FRANCE/202103_OSM2IGEO_23_HAUTE_NORMANDIE_SHP_L93_2154.zip +* Extraction de données d'**OpenStreetMap** dans un format SIG, sous licence "ODBL" (site https://github.com/igeofr/osm2igeo ). On utilisera par exemple les données de l'ancienne région Haute-Normandie. -* Données cadastrales (site https://cadastre.data.gouv.fr ), sous licence Par exemple pour la Seine-Maritime: -https://cadastre.data.gouv.fr/data/etalab-cadastre/2019-01-01/shp/departements/76/ +* Données cadastrales (site https://cadastre.data.gouv.fr ), sous licence "Licence Ouverte 2.0" Par exemple pour la Seine-Maritime : +https://cadastre.data.gouv.fr/data/etalab-cadastre/2024-10-01/shp/departements/76/ -* PLU (site https://www.geoportail-z_formation.gouv.fr/map/ ). Par exemple les données de la ville du Havre: -https://www.geoportail-z_formation.gouv.fr/map/#tile=1&lon=0.13496041707835396&lat=49.49246433172931&zoom=12&mlon=0.117760&mlat=49.502918 -Cliquer sur la commune, et utiliser le lien de téléchargement, actuellement: +* PLU (site https://www.geoportail-urbanisme.gouv.fr/map/ ). Par exemple les données de la ville du Havre. Cliquer sur la commune, et utiliser le lien de téléchargement. Ces données peuvent aussi être importées dans la base de formation via les outils de QGIS. -## Concepts de base de données: +## Concepts de base de données Un rappel sur les concepts de table, champs, relations. diff --git a/docs/media/qgis_connexion_PostgreSQL.png b/docs/media/qgis_connexion_PostgreSQL.png new file mode 100644 index 0000000..225c758 Binary files /dev/null and b/docs/media/qgis_connexion_PostgreSQL.png differ diff --git a/docs/media/qgis_creer_schema_explorateur.png b/docs/media/qgis_creer_schema_explorateur.png new file mode 100644 index 0000000..238b5a9 Binary files /dev/null and b/docs/media/qgis_creer_schema_explorateur.png differ diff --git a/docs/media/qgis_creer_table_explorateur.png b/docs/media/qgis_creer_table_explorateur.png new file mode 100644 index 0000000..caa6541 Binary files /dev/null and b/docs/media/qgis_creer_table_explorateur.png differ diff --git a/docs/media/qgis_rendu_simplification_fournisseur.png b/docs/media/qgis_rendu_simplification_fournisseur.png new file mode 100644 index 0000000..68d4d6d Binary files /dev/null and b/docs/media/qgis_rendu_simplification_fournisseur.png differ diff --git a/docs/media/qgis_traitement_exporter_dialogue_algorithme.png b/docs/media/qgis_traitement_exporter_dialogue_algorithme.png new file mode 100644 index 0000000..bac2b18 Binary files /dev/null and b/docs/media/qgis_traitement_exporter_dialogue_algorithme.png differ diff --git a/docs/media/qgis_traitement_exporter_postgresql_ogr.png b/docs/media/qgis_traitement_exporter_postgresql_ogr.png new file mode 100644 index 0000000..004183a Binary files /dev/null and b/docs/media/qgis_traitement_exporter_postgresql_ogr.png differ diff --git a/docs/postgresql_in_qgis.md b/docs/postgresql_in_qgis.md index af61b52..2b86d83 100644 --- a/docs/postgresql_in_qgis.md +++ b/docs/postgresql_in_qgis.md @@ -4,66 +4,93 @@ Lorsqu'on travaille avec des données **PostgreSQL**, QGIS n'accède pas à la donnée en lisant un ou plusieurs fichiers, mais fait des **requêtes** à la base, à chaque fois qu'il en a besoin: déplacement de carte, zoom, ouverture de la table attributaire, sélection par expression, etc. -* QGIS se connecte à la base de données, et récupère des données qui sont stockées dans des tables. Il doit donc **télécharger la donnée** à chaque action (pas de cache car la donnée peut changer entre temps). -* une table équivaut à une couche SIG, définie par un nom, une liste de champs typés, et un ou plusieurs champs de géométrie. -* une géométrie est caractérisée par un type (polygone, point, ligne, etc.), une dimension (2D ou 3D) et une projection (Ex: EPSG:2154) codifiée via un SRID ( Ex: 2154) -* certaines tables n'ont pas de géométrie: on les appelle alors non spatiales. QGIS sait les exploiter, ce qui permet de stocker des informations de contexte (nomenclature, événements). +* QGIS **se connecte** à la base de données, et récupère des données qui sont stockées dans des tables. Il doit donc **télécharger la donnée** à chaque action (pas de cache car la donnée peut changer entre temps). +* une **table** équivaut à une **couche SIG**, définie par un nom, une **liste de champs typés**, et un ou plusieurs champs de **géométrie**. +* une **géométrie** est caractérisée par un **type** (polygone, point, ligne, etc.), une **dimension** (2D ou 3D) et une **projection** (Ex: EPSG:2154) codifiée via un SRID (Ex: 2154) +* certaines tables n'ont pas de géométrie: on les appelle alors **non spatiales**. QGIS sait les exploiter, ce qui permet de stocker des informations de contexte (nomenclature, événements). La base de données fournit donc un lieu de stockage des données centralisé. On peut gérer les droits d'accès ou d'écriture sur les schémas et les tables. ## Créer une connexion QGIS à la base de données -Dans QGIS, il faut **créer une nouvelle connexion** à PostgreSQL, via l'outil "Éléphant" : menu **Couches / Ajouter une couche / Ajouter une couche PostgreSQL** . Configurer les options suivantes: +Dans QGIS, il faut **créer une nouvelle connexion** à PostgreSQL, via l'outil "Éléphant" : menu **Couches / Ajouter une couche / Ajouter une couche PostgreSQL**. Configurer les options suivantes : -* laisser le champ **Service** vide +* laisser le champ **Service** vide (sauf si vous savez utiliser les fichiers de service PostgreSQL, ce qui est recommandé) * cocher les cases **Enregistrer** à côté de l'utilisateur et du mot de passe, après avoir **Tester la connexion** (via le bouton dédié) -* cocher la case en bas **Utiliser la table de métadonnées estimées** +* cocher les cases en bas **Lister les tables sans géométries** et **Utiliser la table de métadonnées estimées** * Valider +![Nouvelle connexion PostGIS dans QGIS](media/qgis_connexion_PostgreSQL.png) + **Attention** Pour plus de sécurité, privilégier l'usage d'un service PostgreSQL: -https://docs.qgis.org/latest/fr/docs/user_manual/managing_data_source/opening_data.html#pg-service-file +https://docs.qgis.org/latest/fr/docs/user_manual/managing_data_source/opening_data.html#pg-service-file (plugin QGIS intéressant : PG Service Parser) + +Il est aussi intéressant pour les **performances** d'accès aux données PostgreSQL de modifier une option dans les options de QGIS, onglet **Rendu** : il faut cocher la case **Réaliser la simplification par le fournisseur de données lorsque c'est possible**. Cela permet de télécharger des versions allégées des données aux petites échelles. [Documentation QGIS](https://docs.qgis.org/latest/fr/docs/user_manual/introduction/qgis_configuration.html#rendering-settings) + +![Simplification rendu vecteur](media/qgis_rendu_simplification_fournisseur.png) -Il est aussi intéressant pour les **performances** d'accès aux données PostgreSQL de modifier une option dans les options de QGIS, onglet **Rendu**: il faut cocher la case **Réaliser la simplification par le fournisseur de données lorsque c'est possible**. Cela permet de télécharger des versions allégées des données aux petites échelles. [Documentation](https://docs.qgis.org/latest/fr/docs/user_manual/introduction/qgis_configuration.html#rendering-settings) +**NB** Pour les couches PostGIS qui auraient déjà été ajoutées **avant d'avoir activé cette option**, vous pouvez manuellement changer dans vos projets via l'onglet **Rendu** de la boîte de dialogue des propriétés de chaque couche PostGIS. -**NB** Pour les couches PostGIS qui auraient déjà été ajoutées avant d'avoir activé cette option, vous pouvez manuellement changer dans vos projets via l'onglet **Rendu** de la boîte de dialogue des propriétés de chaque couche PostGIS. ## Ouvrir une couche PostgreSQL dans QGIS -Trois solutions sont possibles: +Trois solutions sont possibles : -* **utiliser l'explorateur** : seulement pour les tables spatiales, sauf si on a coché **Lister les tables sans géométries** dans les propriétés de la connexion. Le panneau présente un arbre qui liste les schémas, puis les tables ou vues exploitables. Une icône devant chaque table/vue indique si une table est géométrique ou non ainsi que le type de géométrie, point, ligne ou polygône. -* utiliser le menu **Couche / Ajouter une couche**. La boite de dialogue propose de se connecter, puis liste les schémas et les tables +* **utiliser l'explorateur** : Le panneau présente un arbre qui liste les `schémas`, puis les `tables` ou `vues` exploitables. Une icône devant chaque table/vue indique si une table est géométrique ou non ainsi que le type de géométrie, point, ligne ou polygone. On peut utiliser le menu `Clic-Droit` sur les objets de l'arbre. +* utiliser le menu **Couche / Ajouter une couche**. La boite de dialogue propose de se connecter, puis liste les schémas et les tables (ancienne méthode pas recommandée) * utiliser le **Gestionnaire de base de données**, qui présente une fenêtre QGIS séparée dédiée aux manipulations sur les données. -## Le Gestionnaire de base de données +## Création de schémas et de tables + +On peut travailler avec le gestionnaire de bases de données de QGIS : menu **Base de données > Gestionnaire BD** (sinon via l'icône de la barre d’outil base de données) ou avec l'**explorateur** (recommandé). + +Dans l'arbre qui se présente, on peut **choisir sa connexion**, puis double-cliquer, ce qui montre l'ensemble des **schémas**, et l'ouverture d'un schéma montre la liste des tables et vues. Les menus permettent de créer ou d'éditer des objets (schémas, tables). + +Une **fenêtre SQL** permet de lancer manuellement des requêtes SQL. Nous allons principalement utiliser cet outil : menu **Base de données / Fenêtre SQL** (on peut aussi le lancer via F2). + +NB: C'est possible aussi d'utiliser le **fenêtre SQL de l'explorateur** via clic-droit `Exécuter le SQL ...`, mais elle ne permet pas encore de ne lancer que le **texte surligné**, ce qui est pourtant très pratique pendant une formation. + +### Création du schéma + +Les **schémas** dans une base PostgreSQL sont utiles pour regrouper les tables. -On travaille via QGIS, avec le gestionnaire de bases de données : menu **Base de données > Gestionnaire BD** (sinon via l'icône de la barre d’outil base de données). +On recommande de ne pas créer de tables dans le schéma `public`, mais d'utiliser des schémas (par thématique, pour la gestion des droits, etc.). -Dans l'arbre qui se présente à gauche du gestionnaire de bdd, on peut **choisir sa connexion**, puis double-cliquer, ce qui montre l'ensemble des **schémas**, et l'ouverture d'un schéma montre la liste des tables et vues. Les menus du gestionnaire permettent de créer ou d'éditer des objets (schémas, tables). +Pour la formation, nous allons créer un schéma `z_formation` : -Une **fenêtre SQL** permet de lancer manuellement des requêtes SQL. Nous allons principalement utiliser cet outil : menu **Base de données / Fenêtre SQL** (on peut aussi le lancer via F2). : +* Dans l'explorateur, faire un clic-droit sur le nom de la connexion et `Créer un schéma`. -### Création de tables +![Créer un schéma](media/qgis_creer_schema_explorateur.png) -Depuis **QGIS**: dans le gestionnaire de base de données, menu ** Table / Créer une table**: +### Création d'une table + +Ensuite, on peut créer une **table** dans ce schéma : dans l'explorateur, faire un clic-droit sur le schéma `z_formation`, puis `Nouvelle table...` : * choisir le **schéma** et le **nom** de la table, en minuscule, sans accents ni caractères complexes -* Via le bouton **Ajouter un champ**, on commence par ajouter un champ **id** de type **serial** (entier auto-incrémenté), puis d'autres champs en choisissant le nom et le type. Choisir des noms de champ simples ! +* Via le bouton **Ajouter un champ**, on crée autant de champs que nécessaire en choisissant le nom et le type. **Choisir des noms de champ simples sans majuscule, espace ni accents !**. * Choisir dans la liste déroulante le **champ de clé primaire** (ici id) * Cocher **Créer une colonne géométrique** et choisir le type et le SRID (par exemple 2154 pour le Lambert 93) * Cocher **Créer un index spatial** -**NB**: on a créé une table dans cet exemple `z_formation.borne_incendie` avec les champs **id_borne** (text), **code** (text), **debit** (real) et **geom** (géométrie de type Point, code SRID 2154) -**Créer une table en SQL** +![Créer une table](media/qgis_creer_table_explorateur.png) + +**NB**: on a créé une table dans cet exemple `z_formation.borne_incendie` avec les champs **code** (text), **debit** (real) et **geom** (géométrie de type Point, code SRID 2154) + +* Un champ `id` de type **entier auto-incrémenté** a été créé automatiquement par QGIS en tant que **clé primaire** de la table. +* Un **index spatial** a aussi été créé par QGIS sur le champ de géométrie. + +### Utiliser du SQL au lieu des menus de QGIS + +On peut aussi utiliser du **SQL** pour créer des objets dans la base : ```sql -- création d'un schéma CREATE SCHEMA IF NOT EXISTS z_formation; -- création de la table -CREATE TABLE z_formation.borne_incendie ( +CREATE TABLE IF NOT EXISTS z_formation.borne_incendie ( -- un serial est un entier auto-incrémenté id_borne serial NOT NULL PRIMARY KEY, code text NOT NULL, @@ -78,9 +105,9 @@ CREATE INDEX ON z_formation.borne_incendie USING GIST (geom); ### Ajouter des données dans une table -On peut bien sûr charger la table dans QGIS, puis utiliser les outils d'édition classique pour créer des nouveaux objets. +On peut bien sûr charger la table dans QGIS, puis utiliser les **outils d'édition** classique pour créer des nouveaux objets ou les modifier. -En SQL, il est aussi possible d'insérer des données ( https://sql.sh/cours/insert-into ). Par exemple pour les bornes à incendie: +En SQL, il est aussi possible d'insérer des données ( https://sql.sh/cours/insert-into ). Par exemple pour les bornes à incendie : ```sql @@ -93,45 +120,14 @@ INSERT INTO z_formation.borne_incendie (code, debit, geom) ; ``` -**NB**: Nous verrons plus loin l'utlisation de fonctions de création de géométrie, comme **ST_MakePoint** - - -## Création d’un schéma z_formation dans la base - -* ajout du schéma via le gestionnaire de bdd, ou via une requête: +**NB**: Nous verrons plus loin l'utilisation de fonctions de création de géométrie, comme **ST_MakePoint** -```sql -CREATE SCHEMA IF NOT EXISTS z_formation; -``` - -* modification des droits d’accès à ce schéma, si besoin: - -```sql --- On donne ici tous les droits à "utilisateur" -GRANT ALL PRIVILEGES ON SCHEMA z_formation TO "utilisateur"; -``` - -* suppression d'un schéma - -```sql --- Suppression du schéma si il est vide -DROP SCHEMA monschema; - --- suppression du schéma et de toutes les tables de ce schéma (via CASCADE) !!! ATTENTION !!! -DROP SCHEMA monschema CASCADE; -``` - -* renommer un schéma - -```sql -ALTER SCHEMA monschema RENAME TO unschema; -``` ## Vérifier et créer les indexes spatiaux On peut vérifier si chaque table contient un **index spatial** via le gestionnaire de base de données de QGIS, en cliquant sur la table dans l'arbre, puis en regardant les informations de l'onglet **Info**. On peut alors créer l'index spatial via le lien bleu **Aucun index spatial défini (en créer un)**. -Sinon, il est possible de le faire en SQL via la requête suivante: +Sinon, il est possible de le faire en SQL via la requête suivante : ```sql CREATE INDEX ON nom_du_schema.nom_de_la_table USING GIST (geom);