Suite

Quelle est la syntaxe correcte pour Exécuter SQL dans le traitement de QGIS 2.6 ?

Quelle est la syntaxe correcte pour Exécuter SQL dans le traitement de QGIS 2.6 ?


J'ai fait un petit modèle avec Processing dans QGIS 2.6.

La couche finale doit être le résultat d'une requête SQL. Maintenant, dans leExécuter SQLfenêtre de dialogue, je peux ajouter la requête :

sélectionnez le nom, max(ele) comme ele, geom du groupe layer_id par id

mais je n'ai pas compris quel nom dois-je spécifier dans la requête (id_couchedans l'exemple).


Paramètres Database [string] Nom de la base de données, pas le nom de la connexion. Par défaut, vous n'avez pas à renseigner le nom, la connexion à la base de données actuelle sera choisie.

Par défaut : (non défini)

Requête SQL [chaîne] Définit la requête SQL, par exemple 'create schema test;'.

Par défaut : (non défini)


MODIFIER TABLE

ALTER TABLE vous permet d'ajouter des colonnes à une table dans une base de données.

ET est un opérateur qui combine deux conditions. Les deux conditions doivent être vraies pour que la ligne soit incluse dans le jeu de résultats.

AS est un mot-clé en SQL qui vous permet de renommer une colonne ou une table à l'aide d'un alias.

AVG() est une fonction d'agrégat qui renvoie la valeur moyenne d'une colonne numérique.

ENTRE

L'opérateur BETWEEN est utilisé pour filtrer le jeu de résultats dans une certaine plage. Les valeurs peuvent être des nombres, du texte ou des dates.

Les instructions CASE sont utilisées pour créer différentes sorties (généralement dans l'instruction SELECT). C'est la façon dont SQL gère la logique si-alors.

COMPTER()

COUNT() est une fonction qui prend le nom d'une colonne comme argument et compte le nombre de lignes où la colonne n'est pas NULL .

CRÉER UN TABLEAU

CREATE TABLE crée une nouvelle table dans la base de données. Il vous permet de spécifier le nom de la table et le nom de chaque colonne de la table.

EFFACER

Les instructions DELETE sont utilisées pour supprimer des lignes d'une table.

PAR GROUPE

GROUP BY est une clause SQL qui n'est utilisée qu'avec les fonctions d'agrégat. Il est utilisé en collaboration avec l'instruction SELECT pour organiser des données identiques en groupes.

AYANT

HAVING a été ajouté à SQL car le mot clé WHERE ne pouvait pas être utilisé avec les fonctions d'agrégation.

JOINTURE INTERNE

Une jointure interne combinera les lignes de différentes tables si le condition d'adhésion est vrai.

INSÉRER

Les instructions INSERT sont utilisées pour ajouter une nouvelle ligne à une table.

EST NULL / N'EST PAS NULL

IS NULL et IS NOT NULL sont des opérateurs utilisés avec la clause WHERE pour tester les valeurs vides.

LIKE est un opérateur spécial utilisé avec la clause WHERE pour rechercher un modèle spécifique dans une colonne.

LIMITE

LIMIT est une clause qui vous permet de spécifier le nombre maximum de lignes que l'ensemble de résultats aura.

MAX() est une fonction qui prend le nom d'une colonne comme argument et renvoie la plus grande valeur de cette colonne.

MIN() est une fonction qui prend le nom d'une colonne comme argument et renvoie la plus petite valeur de cette colonne.

OR est un opérateur qui filtre le jeu de résultats pour n'inclure que les lignes où l'une ou l'autre des conditions est vraie.

COMMANDÉ PAR

ORDER BY est une clause qui indique que vous souhaitez trier le jeu de résultats par une colonne particulière par ordre alphabétique ou numérique.

JOINT EXTÉRIEUR

Une jointure externe combinera des lignes de différentes tables même si la condition de jointure n'est pas remplie. Chaque rangée du la gauche table est renvoyée dans le jeu de résultats, et si la condition de jointure n'est pas remplie, les valeurs NULL sont utilisées pour remplir les colonnes de la droite tableau.

TOUR()

ROUND() est une fonction qui prend un nom de colonne et un entier comme arguments. Il arrondit les valeurs de la colonne au nombre de décimales spécifié par l'entier.

SÉLECTIONNER

Les instructions SELECT sont utilisées pour extraire des données d'une base de données. Chaque requête commencera par SELECT .

SÉLECTIONNER DISTINCT

SELECT DISTINCT spécifie que l'instruction sera une requête qui renvoie des valeurs uniques dans la ou les colonnes spécifiées.

SUM() est une fonction qui prend le nom d'une colonne comme argument et renvoie la somme de toutes les valeurs de cette colonne.

METTRE À JOUR

Les instructions UPDATE vous permettent de modifier les lignes d'une table.

WHERE est une clause qui indique que vous souhaitez filtrer le jeu de résultats pour inclure uniquement les lignes où les éléments suivants état est vrai.

La clause WITH vous permet de stocker le résultat d'une requête dans une table temporaire à l'aide d'un alias. Vous pouvez également définir plusieurs tables temporaires à l'aide d'une virgule et d'une instance du mot clé WITH.

La clause WITH est également connue sous le nom d'expression de table commune (CTE) et de factorisation de sous-requête.


3 réponses 3

Pour les SGBDR modernes, il n'y a pas de différence entre "JOIN explicite" et "JOIN-in-the-WHERE" (si tous les JOINS sont INNER) en ce qui concerne les performances et le plan de requête.

La syntaxe JOIN explicite est plus claire et moins ambiguë (voir les liens ci-dessous)

Maintenant, le JOIN-before-WHERE est logique traitement non réel traitement et les optimiseurs modernes sont assez intelligents pour s'en rendre compte.

Votre problème ici est probablement l'indexation.

Veuillez nous montrer tous les index et clés de ces tables. Et les plans de requête

Remarque : cette question aurait été proche sur StackOverflow pour être un doublon à ce jour. COUNT(1) vs COUNT(*) est également un autre mythe brisé.

Vous devez refactoriser complètement la requête

Essayez d'effectuer les clauses WHERE plus tôt et les JOIN plus tard

Même si vous exécutez un plan EXPLAIN sur cette requête refactorisée et que cela semble pire que votre original, essayez-le quand même. Les tables temporaires créées en interne effectueront des jointures cartésiennes, mais ces tables sont plus petites.

@gbn a mentionné s'assurer que vous avez les bons index en place. Dans ce cas, veuillez indexer la colonne créée dans MasterTable.

MISE À JOUR 2011-06-24 22:31 HAE

Vous devez exécuter ces requêtes :

Si NullRoles X 20 < AllRoles (en d'autres termes, si NullRoles est inférieur à 5% des lignes de la table), vous devez créer un index non unique le rôle dans UserTable. Sinon, une table complète de UserTable suffirait car l'optimiseur de requête peut éventuellement exclure l'utilisation d'un index.

MISE À JOUR 2011-06-25 12:40 HAE

Étant donné que je suis un DBA MySQL, ma méthode de travail nécessite de ne pas faire confiance à l'optimiseur de requête MySQL par pessimisme positif et être conservateur. Ainsi, je vais essayer de refactoriser une requête ou de créer les index de couverture nécessaires pour devancer les mauvaises habitudes cachées de l'optimiseur de requête MySQL. La réponse de @gbn semble plus complète dans la mesure où SQL Server peut avoir plus de "solidité d'esprit" pour évaluer les requêtes.


Requêtes temporelles

35.6.2.1 Tableau des périodes de rapport

Puisque SQL est un langage de base de données, nous préférons faire des recherches et non des calculs. Ils peuvent être optimisés alors que les mathématiques temporelles gâchent l'optimisation. Un idiome utile est un calendrier de période de rapport que tout le monde utilise, il n'y a donc aucun moyen d'obtenir des désaccords dans la DML.

Le tableau des périodes de rapport donne un nom à une plage de dates commune à l'ensemble de l'entreprise.

CREATE TABLE Something_Report_Periods

(something_report_name CHAR(10) CLÉ PRIMAIRE NON NULLE

CHECK (something_report_name LIKE < pattern >),

quelque chose_report_start_date DATE NON NULL,

quelque chose_report_end_date DATE NON NULL,

VÉRIFIER (something_report_start_date <= quelque chose_report_end_date),

Ces périodes de rapport peuvent se chevaucher ou présenter des lacunes. Donner un nom à une période est plus difficile que vous ne le pensez. J'aime la convention MySQL d'utiliser des doubles zéros pendant des mois et des années, c'est-à-dire "aaaa-mm-00" pour un mois dans l'année et "aaaa-00-00" pour toute l'année. Les avantages sont qu'il triera avec le format de données ISO-8601 requis par le SQL standard et qu'il est indépendant du langage. Le modèle de validation est '[12][0-9][0-9][0-9]-00-00' et '[12][0-9][0-9][0-9]- [01][0-9]-00'.


C'est probablement comme ça que je ferais. Cela exécutera le travail toutes les 4 heures, aux heures de 00:00, 04:00, 08:00 12:00, 16:00, 20:00.

C'est juste une façon un peu plus verbeuse d'écrire */4, mais cela devrait fonctionner de la même manière.

Le message d'origine, avant édition, montrait la configuration comme suit :

L'affiche n'était pas familière avec Markdown et a mis un astérisque dans la première colonne, ce qui l'a fait apparaître comme une balle. J'ai édité leur message pour refléter ce qu'ils avaient l'intention de publier :

Dans cette configuration, l'affiche obtiendrait le comportement qu'elle a observé : la tâche s'exécutera une fois par minute pendant des heures qui sont divisibles par 4.

Pour éviter de courir une fois par minute, un nombre est nécessaire dans la première colonne, comme ceci :

Cela se déroulera à la 15e minute après chaque heure.

En résumé : pour exécuter une fois par heure pendant des heures qui sont également divisibles par 4, utilisez cette syntaxe :


2 réponses 2

Garantie de 100% sûr de l'injection SQL ? Je ne l'aurai pas (de moi).

En principe, votre base de données (ou bibliothèque dans votre langage qui interagit avec la base de données) pourrait implémenter des instructions préparées avec des paramètres liés d'une manière dangereuse susceptible d'une sorte d'attaque avancée, par exemple en exploitant des débordements de tampon ou en ayant des caractères de fin null dans user- chaînes fournies, etc. (Vous pourriez argumenter que ces types d'attaques ne devraient pas être appelés injection SQL car ils sont fondamentalement différents, mais ce n'est que de la sémantique).

Je n'ai jamais entendu parler d'aucune de ces attaques contre des instructions préparées sur de vraies bases de données sur le terrain et je suggère fortement d'utiliser des paramètres liés pour empêcher l'injection SQL. Sans paramètres liés ni assainissement d'entrée, il est trivial d'effectuer une injection SQL. Avec seulement l'assainissement d'entrée, il est assez souvent possible de trouver une échappatoire obscure autour de l'assainissement.

Avec les paramètres liés, votre plan d'exécution de requête SQL est défini à l'avance sans dépendre de l'entrée de l'utilisateur, ce qui devrait rendre l'injection SQL impossible (car les guillemets insérés, les symboles de commentaire, etc. ne sont insérés que dans l'instruction SQL déjà compilée).

Le seul argument contre l'utilisation d'instructions préparées est que vous souhaitez que votre base de données optimise vos plans d'exécution en fonction de la requête réelle. La plupart des bases de données, lorsqu'elles reçoivent la requête complète, sont suffisamment intelligentes pour effectuer un plan d'exécution optimal. enregistrements, vous pouvez effectuer une recherche basée sur un index [1].

ÉDITER: Répondant à deux critiques (un peu trop longues pour des commentaires) :

Premièrement, comme d'autres l'ont noté, oui, chaque base de données relationnelle prenant en charge les instructions préparées et les paramètres liés ne précompile pas nécessairement l'instruction préparée sans examiner la valeur des paramètres liés. De nombreuses bases de données le font habituellement, mais il est également possible pour les bases de données de consulter les valeurs des paramètres liés lors de la détermination du plan d'exécution. Ce n'est pas un problème, car la structure de l'instruction préparée avec des paramètres liés séparés permet à la base de données de différencier facilement l'instruction SQL (y compris les mots-clés SQL) des données dans les paramètres liés (où rien dans un paramètre lié ne sera interprété comme un mot-clé SQL). Cela n'est pas possible lors de la construction d'instructions SQL à partir d'une concaténation de chaînes où les variables et les mots-clés SQL seraient mélangés.

Deuxièmement, comme le souligne l'autre réponse, l'utilisation de paramètres liés lors de l'appel d'une instruction SQL à un moment donné d'un programme empêchera en toute sécurité l'injection SQL lors de cet appel de niveau supérieur. Cependant, si vous avez des vulnérabilités d'injection SQL ailleurs dans l'application (par exemple, dans les fonctions définies par l'utilisateur que vous avez stockées et exécutées dans votre base de données que vous avez écrites de manière non sécurisée pour construire des requêtes SQL par concaténation de chaînes).

Par exemple, si dans votre application vous avez écrit un pseudo-code comme :

Il ne peut y avoir d'injection SQL lors de l'exécution de cette instruction SQL au niveau de l'application. Cependant, si la fonction de base de données définie par l'utilisateur a été écrite de manière non sécurisée (en utilisant la syntaxe PL/pgSQL) :

alors vous seriez vulnérable aux attaques par injection SQL, car il exécute une instruction SQL construite via la concaténation de chaînes qui mélange l'instruction SQL avec des chaînes contenant les valeurs des variables définies par l'utilisateur.

Cela dit, à moins que vous n'essayiez d'être dangereux (en construisant des instructions SQL via la concaténation de chaînes), il serait plus naturel d'écrire le défini par l'utilisateur de manière sûre comme :

De plus, si vous ressentez vraiment le besoin de composer une instruction SQL à partir d'une chaîne dans une fonction définie par l'utilisateur, vous pouvez toujours séparer les variables de données de l'instruction SQL de la même manière que les paramètres storage_procedures/bound, même dans une fonction définie par l'utilisateur. Par exemple en PL/pgSQL :

Ainsi, l'utilisation d'instructions préparées est à l'abri de l'injection SQL, tant que vous ne faites pas simplement des choses dangereuses ailleurs (c'est-à-dire la construction d'instructions SQL par concaténation de chaînes).


Une autre façon est d'utiliser cette commande dans le fichier batch :

J'ai trouvé que c'était la meilleure solution et cela fonctionne dans un terminal ou dans un script :

Réalisant maintenant que votre problème peut être lié au fichier sql lui-même, sachez qu'il faut dire à sqlplus de se fermer. La façon dont je fais c'est :

(La barre oblique est importante. Elle indique à sqlplus d'exécuter le ou les états au-dessus.)

Le meilleur moyen de masquer les informations utilisateur et les sorties est :

exit est fourni à la sortie de sqlplus le forçant à quitter. -S supprime toutes les sorties du serveur autres que les requêtes SQL dans le script.

Vous pouvez également le faire dans votre script shell.

Vous devrez peut-être échapper le "" avec un .

Oui, c'est possible - générez un script wrapper qui configure SQLPlus de manière appropriée, inclut votre script (c'est-à-dire @YourTargetScript.sql ), puis effectue une sortie.

Cela dit, je ne recommande pas du tout cette approche. séparation saine de la sortie entre stdout/stderr, la prise en charge native de la sortie CSV et d'autres fonctionnalités similaires), et cela a beaucoup mieux fonctionné.

Si vous le placez dans un fichier batch, le contrôle continuera avec les instructions qui le suivent.


Limites

Outre les limitations générales des requêtes fédérées, les bases de données Cloud SQL présentent les limitations suivantes.

Types de données non pris en charge

Si votre requête externe contient un type de données non compatible avec BigQuery, la requête échouera immédiatement. Vous pouvez convertir le type de données non pris en charge en un autre type de données MySQL ou PostgreSQL pris en charge.

Type de données MySQL non pris en charge

  • Message d'erreur: Fonction table non valide external_query Type MySQL non pris en charge trouvé dans BigQuery à [1:15]
  • Type non pris en charge : GÉOMÉTRIE , MÈCHE
  • Résolution: Convertissez le type de données non pris en charge en STRING.
  • Exemple: SELECT ST_AsText(ST_GeomFromText('POINT(1 1)')) Cette commande convertit le type de données non pris en charge GEOMETRY en STRING .

Type de données PostgreSQL non pris en charge

  • Message d'erreur: Le type de fonction external_query Postgres (OID = 790) non valide n'est pas pris en charge actuellement à [1:15]
  • Type non pris en charge : argent , heure avec fuseau horaire , inet , chemin , pg_lsn , point , polygone , tsquery , tsvector , txid_snapshot , uuid , boîte , cidr , cercle , intervalle , jsonb , ligne , lseg , macaddr , macaddr8
  • Résolution: Convertissez le type de données non pris en charge en STRING.
  • Exemple: SELECT CAST(཈.34'::float8::numeric::money AS varchar(30)) Cette commande convertit le type de données non pris en charge money en STRING .

Tableau des températures

Une table temporaire est littéralement une table créée sur disque, juste dans une base de données spécifique dont tout le monde sait qu'elle peut être supprimée. Il est de la responsabilité d'un bon développeur de détruire ces tables lorsqu'elles ne sont plus nécessaires, mais un DBA peut également les effacer.

Les tables temporaires se présentent sous deux formes : locales et globales. En termes de MS Sql Server, vous utilisez une désignation #tableName pour local et ##tableName pour global (notez l'utilisation d'un simple ou double # comme caractéristique d'identification).

Notez qu'avec les tables temporaires, par opposition aux variables de table ou CTE, vous pouvez appliquer des index et autres, car ce sont légitimement des tables au sens normal du terme.

En général, j'utiliserais des tables temporaires pour des requêtes plus longues ou plus volumineuses, et des CTE ou des variables de table si j'avais déjà un petit ensemble de données et que je voulais simplement écrire rapidement un peu de code pour quelque chose de petit. L'expérience et les conseils des autres indiquent que vous devez utiliser des CTE où vous avez un petit nombre de lignes renvoyées. Si vous en avez un grand nombre, vous bénéficierez probablement de la possibilité d'indexer sur la table temporaire.

La réponse acceptée ici dit "un CTE ne devrait jamais être utilisé pour la performance" - mais cela pourrait induire en erreur. Dans le contexte des CTE par rapport aux tables temporaires, je viens de terminer de supprimer une partie des déchets d'une suite de processus stockés, car certains doofus ont dû penser qu'il y avait peu ou pas de surcharge à utiliser des tables temporaires. J'ai poussé le lot dans les CTE, à l'exception ceux qui allaient légitimement être réutilisés tout au long du processus. J'ai gagné environ 20% de performances selon toutes les métriques. J'ai ensuite entrepris de supprimer tous les curseurs qui tentaient d'implémenter un traitement récursif. C'est là que j'ai vu le plus grand gain. J'ai fini par réduire les temps de réponse d'un facteur dix.

Les CTE et les tables temporaires ont des cas d'utilisation très différents. Je veux juste souligner que, bien que n'étant pas une panacée, la compréhension et l'utilisation correcte des CTE peuvent conduire à des améliorations vraiment remarquables à la fois en termes de qualité/maintenabilité et de vitesse du code. Depuis que je les maîtrise, je considère les tables temporaires et les curseurs comme les grands maux du traitement SQL. Je peux très bien me débrouiller avec les variables de table et les CTE pour presque tout maintenant. Mon code est plus propre et plus rapide.

Un CTE peut être appelé à plusieurs reprises dans une requête et est évalué à chaque fois qu'il est référencé - ce processus peut être récursif. S'il n'est référencé qu'une seule fois, il se comporte comme une sous-requête, bien que les CTE puissent être paramétrés.

Une table temporaire est physiquement persistante et peut être indexée. En pratique, l'optimiseur de requête peut également conserver les résultats de jointure intermédiaire ou de sous-requête en arrière-plan, comme dans les opérations de spool, il n'est donc pas strictement vrai que les résultats des CTE ne sont jamais conservés sur le disque.

Les variables de table IIRC (en revanche) sont toujours des structures en mémoire.

La table temporaire est un véritable objet dans tempdb, mais cte n'est qu'une sorte de wrapper autour d'une requête complexe pour simplifier la syntaxe d'organiser la récursivité en une seule étape.

La principale raison d'utiliser les CTE est d'accéder aux fonctions de fenêtre telles que row_number() et divers autres.

Cela signifie que vous pouvez faire des choses comme obtenir la première ou la dernière rangée par groupe TRÈS TRÈS rapidement et efficacement - plus efficacement que d'autres moyens dans la plupart des cas pratiques.

Vous pouvez exécuter une requête similaire à celle ci-dessus en utilisant une sous-requête corrélée ou en utilisant une sous-requête, mais le CTE sera plus rapide dans presque tous les scénarios.

De plus, les CTE peuvent vraiment aider à simplifier votre code. Cela peut entraîner des gains de performances car vous comprenez mieux la requête et pouvez introduire plus de logique métier pour aider l'optimiseur à être plus sélectif.

De plus, les CTE peuvent améliorer les performances si vous comprenez votre logique métier et savez quelles parties de la requête doivent être exécutées en premier - généralement, placez vos requêtes les plus sélectives en premier qui conduisent à des ensembles de résultats pouvant utiliser un index dans leur prochaine jointure et ajoutez l'option (ordre de force) indice de requête

Enfin, les CTE n'utilisent pas tempdb par défaut, vous réduisez donc les conflits sur ce goulot d'étranglement grâce à leur utilisation.

Les tables temporaires doivent être utilisées si vous devez interroger les données plusieurs fois, ou si vous mesure vos requêtes et découvrez qu'en insérant dans une table temporaire, puis en ajoutant un index, vos performances sont améliorées.

Il semble y avoir un peu de négativité ici envers les CTE.

Ma compréhension d'un CTE est qu'il s'agit essentiellement d'une sorte de vue ad hoc. SQL est à la fois un langage déclaratif et un langage basé sur des ensembles. Les CTE sont un excellent moyen de déclarer un ensemble ! Ne pas pouvoir indexer un CTE est en fait une bonne chose car vous n'en avez pas besoin ! C'est vraiment une sorte de sucre syntaxique pour rendre la requête plus facile à lire/écrire. Tout optimiseur décent élaborera le meilleur plan d'accès en utilisant des index sur les tables sous-jacentes. Cela signifie que vous pouvez accélérer efficacement votre requête CTE en suivant les conseils d'indexation sur les tables sous-jacentes.

De plus, ce n'est pas parce que vous avez défini un ensemble en tant que CTE que toutes les lignes de l'ensemble doivent être traitées. En fonction de la requête, l'optimiseur peut traiter « juste assez » de lignes pour satisfaire la requête. Peut-être que vous n'aviez besoin que des 20 premiers pour votre écran. Si vous avez construit une table temporaire, vous devez vraiment lire/écrire toutes ces lignes !

Sur cette base, je dirais que les CTE sont une excellente fonctionnalité de SQL et peuvent être utilisés partout où ils rendent la requête plus facile à lire. Je ne penserais qu'à une table temporaire pour un processus par lots qui aurait vraiment besoin de traiter chaque enregistrement. Même dans ce cas, ce n'est pas vraiment recommandé car sur une table temporaire, il est beaucoup plus difficile pour la base de données de vous aider avec la mise en cache et les index. Il peut être préférable d'avoir une table permanente avec un champ PK unique à votre transaction.

Je dois admettre que mon expérience concerne principalement DB2, donc je suppose que CTE fonctionne de manière similaire dans les deux produits. Je me ferai un plaisir de me corriger si les CTE sont en quelque sorte inférieurs au serveur SQL. )


Spécifiez manuellement la langue pour la coloration syntaxique [dupliquer]

Ceci fait suite à une question à laquelle j'ai répondu plus tôt (Modifications apportées à la coloration syntaxique).

Pour la plupart des questions qui ont plus d'une balise liée à la langue et celles avec des langues floues (par exemple .net !), il devrait y avoir une option pour spécifier la langue à utiliser dans la coloration syntaxique car parfois (et assez souvent aussi !) la langue l'inférence est fausse.

Prenez par exemple le scénario que je décris ci-dessous.

Lorsqu'une réponse est donnée dans une langue autre que la "langue principale" (qui se trouve être C#), le code est toujours surligné en C# même s'il n'est pas dans cette langue !

  1. Répondez à toute question comportant plusieurs balises explicites liées au langage.
    Par exemple: Webclient.UploadFile qui est étiqueté c#, .net, vb.net et webclient.
  2. Essayez de répondre à la question avec un code différent du langage « principal ».
    Dans ce cas, essayez de répondre à la question avec le code VB.NET.

Résultats attendus: Le code doit être mis en évidence dans VB.NET.
Résultat actuel: Le code a été mis en évidence en C# !

Solution suggérée
Il devrait y avoir un moyen de définir explicitement le langage pour la coloration syntaxique.

Il s'avère également que poser une question avec plusieurs balises explicites liées au langage peut également vous donner une mauvaise coloration syntaxique !
Vous pouvez essayer de créer une nouvelle question avec les éléments suivants et observer l'aperçu :

Marquez la question comme suit (dans l'ordre spécifique) vb.net, .net c#

Vous remarquerez sans faute que le code C# est correctement mis en surbrillance et pas le code vb.net.

Avertissement
Toutes les observations sont basées sur l'aperçu que vous obtenez lors de la saisie de la question ou de la réponse, de sorte que mon résultat observé peut ne pas être tout à fait correct.


Voir la vidéo: QGIS Tutorial: Clip raster EN