[JAVA] Comment construire un peu délicat avec la génération de requêtes SQL dynamiques

Contexte

J'étais en train de réviser le code d'un nouveau venu (historique PG environ 3 semaines?), Et je générais une requête SQL légèrement intéressante, alors partagez l'histoire. Je parle d'utiliser une sorte de mappeur OR ou Doma, mais laissez cela de côté.

supposition

Ce que je veux faire, c'est qu'il y ait plusieurs zones de saisie sur l'écran de recherche, et les éléments saisis par l'utilisateur sont ajoutés aux conditions de recherche SQL.

À moins que vous n'utilisiez un mappeur OR de type Active Record, vous n'utilisez pas une bibliothèque SQL bidirectionnelle comme Doma.

Si vous en avez envie, vous pouvez découper le SQL dans un fichier externe, mais je pense que l'idée habituelle pour les débutants est de générer dynamiquement des chaînes et de construire du SQL.

Par conséquent, vous générez normalement des requêtes SQL avec des jointures de chaîne dans votre code.

** Cette fois, schéma: ** http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05780-02/scripts.htm#Cihgfecd

Exemple: Une requête lorsque vous souhaitez rechercher "Les ventes sont incluses dans la catégorie d'emploi" et "Le salaire est de 6 millions de yens ou plus" dans la table des employés. Permettez-moi d'omettre le paramètre d'échappement dans la clause Like.

SQL que vous souhaitez générer


SELECT
 em.EMPLOYEE_ID
, em.FIRST_NAME
, em.LAST_NAME
FROM
  EMPLOYEES em
, INNER JOIN JOB_HISTORY jh on (em.EMPLOYEE_ID = jh.EMPLOYEE_ID)
, INNER JOIN JOBS jb on (jh.JOB_ID = jb.JOB_ID)
WHERE 1 = 1
AND CURRENT_DATE BETWEEN jh.START_DATE AND jh.END_DATE
AND jb.JOB_TITLE LIKE '%' || ? || '%';     --Je veux l'ajouter à la condition si spécifié par l'utilisateur
AND jb.SALARY >= ?                         --Je veux l'ajouter à la condition si spécifié par l'utilisateur
;

Habituellement, la présence ou l'absence de combinaison de chaînes de caractères est souvent dérivée de la présence ou de l'absence de la valeur. Mis à part l'utilisation de StringBuilder, je ne sais pas.

python


String sql = ~ ; //réduction. Hypothèse de SQL jusqu'à la première ligne de la clause WHERE.

if (jobTitle != null && jobTitle.length >= 0) {
  sql += "AND jb.JOB_TITLE LIKE '%' || ? || '%'"
}

if (minSalary != null && minSalaly.length >= 0) {
  sql += "AND jb.SALARY >= ?"
}

Cependant, un nouveau venu faisait cela.

jobTitleComment = "";
minSalaryComment = "";
if (jobTitle != null && jobTitle.length >= 0) {
 jobTitleComment = "--";
}

if (minSalary != null && minSalaly.length >= 0) {
 minSalaryComment = "--";
}

String sql = "SELECT"
+ " em.EMPLOYEE_ID"
+ ", em.FIRST_NAME"
+ ", em.LAST_NAME"
+ "FROM"
+ "  EMPLOYEES em"
+ ", INNER JOIN JOB_HISTORY jh on (em.EMPLOYEE_ID = jh.EMPLOYEE_ID)"
+ ", INNER JOIN JOBS jb on (jh.JOB_ID = jb.JOB_ID)"
+ "WHERE 1 = 1"
+ "AND CURRENT_DATE BETWEEN jh.START_DATE AND jh.END_DATE"
+ jobTitleComment + "AND jb.JOB_TITLE LIKE '%' || ? || '%'"  //point
+ minSalaryComment + "AND jb.SALARY >= ?"                     //point
;

Je ne pouvais pas comprendre l'intention quand j'ai regardé Pat, et elle est restée bloquée pendant quelques secondes, mais quand j'ai regardé de près, je n'ai pas pu la comprendre. J'essaie de changer d'utiliser ou non les conditions de recherche SQL avec "-" indiquant un commentaire.

Par exemple, un exemple de génération SQL après exécution lorsqu'aucune des conditions n'est définie est le suivant.

Lorsque la condition de recherche n'est pas définie


SELECT
 em.EMPLOYEE_ID
, em.FIRST_NAME
, em.LAST_NAME
FROM
  EMPLOYEES em
, INNER JOIN JOB_HISTORY jh on (em.EMPLOYEE_ID = jh.EMPLOYEE_ID)
, INNER JOIN JOBS jb on (jh.JOB_ID = jb.JOB_ID)
WHERE 1 = 1
AND CURRENT_DATE BETWEEN jh.START_DATE AND jh.END_DATE
-- AND jb.JOB_TITLE LIKE '%' || ? || '%'  /*★ Les deux seront commentés*/
-- AND jb.SALARY >= ?                                          /*★ Les deux seront commentés*/
;

Puisque la condition de recherche est vide, la condition de raffinement de la clause Where est commentée et invalidée.

Voici un exemple de génération lorsque seul le nom du travail est défini.

Lorsque seul le nom du travail est défini


SELECT
 em.EMPLOYEE_ID
, em.FIRST_NAME
, em.LAST_NAME
FROM
  EMPLOYEES em
, INNER JOIN JOB_HISTORY jh on (em.EMPLOYEE_ID = jh.EMPLOYEE_ID)
, INNER JOIN JOBS jb on (jh.JOB_ID = jb.JOB_ID)
WHERE 1 = 1
AND CURRENT_DATE BETWEEN jh.START_DATE AND jh.END_DATE
AND jb.JOB_TITLE LIKE '%' || 'Ventes' || '%'  /*C'est valable*/
-- AND jb.SALARY >= '??'                      /*Cela reste commenté*/
;

Si la condition de recherche existe, la condition de raffinement correspondante dans la clause Where est valide. Je pensais que c'était étonnamment facile à voir.

Résumé

Recommended Posts

Comment construire un peu délicat avec la génération de requêtes SQL dynamiques
Comment créer un environnement Rails 6 avec Docker
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 6.x)
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 5.x)
Créez une application de recherche simple avec Spring Boot
Créez un terrain de jeu avec Xcode 12
J'ai essayé d'implémenter un mappage OU flexible avec MyBatis Dynamic SQL
Créez une application de recherche de restaurant avec l'API IBM Watson + Guru Navi (avec source)
Comment construire un peu délicat avec la génération de requêtes SQL dynamiques
Comment créer une API avec GraphQL et Rails
[Rails] Comment créer un environnement avec Docker
Comment créer un environnement Pytorch sur Ubuntu
Comment passer d'Eclipse Java à un fichier SQL
Comment créer un environnement Docker avec Gradle pour IntelliJ
[Rails] [Docker] Le copier-coller est OK! Comment créer un environnement de développement Rails avec Docker
Comment supprimer un objet new_record construit avec Rails
Comment générer manuellement un JWT avec Knock in Rails
[Comment insérer une vidéo dans un hameau avec Rails]
Comment quitter Docker pour Mac et créer un environnement de développement Docker avec Ubuntu + Vagrant
Comment créer un environnement de développement Java avec VS Code
Comment interroger Array dans jsonb avec Rails + postgres
Comment construire android-midi-lib
[Java] Comment rompre une ligne avec StringBuilder
Comment réduire même un peu la charge du programme lors de la combinaison de caractères avec JAVA
Comment faire une capture d'écran avec l'émulateur Android Studio
Comment demander un fichier CSV au format JSON avec jMeter
[Ruby] Comment diviser chaque requête GraphQL en fichiers
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~
Apprendre Ruby avec AtCoder 13 Comment créer un tableau à deux dimensions
Comment déplacer une autre classe avec une action de bouton d'une autre classe.
Notes sur la création de Jitsi Meet sur Azure avec docker-compose
Mappage à une classe avec un objet de valeur dans How to My Batis
Comment joindre une table sans utiliser DBFlute et SQL
Comment configurer un proxy avec authentification dans Feign
Comment s'inscrire en tant que client dans Square à l'aide de Tomcat
Comment laisser un commentaire
Comment numéroter (nombre) avec html.erb
Comment mettre à jour avec activerecord-import
Comment insérer une vidéo
Comment créer une méthode
Comment annuler la fusion de cellules dans une plage spécifiée avec POI
Comment créer un fichier jar sans dépendances dans Maven
[Rails 6] Comment créer un écran de saisie de formulaire dynamique à l'aide de cocoon
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ MySQL ~
J'ai essayé d'implémenter un mappage OU flexible avec MyBatis Dynamic SQL
Faisons une application multiplateforme avec JRuby (génération de fichier jar)
Comment renommer un modèle avec des contraintes de clé externes dans Rails
Comment ouvrir un fichier de script à partir d'Ubuntu avec du code VS
Comment créer un environnement Rails + Vue + MySQL avec Docker [dernière version 2020/09]
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Sequelize ~
Vous ne pouvez pas changer la version de facette du projet d'un module Web dynamique à x.x. Comment faire avec
Construire un projet Java avec Gradle
Créer un environnement Node.js avec Docker
Comment démarrer avec Slim