web-dev-qa-db-fra.com

pourquoi utiliseriez-vous l'instruction WHERE 1 = 0 dans SQL?

J'ai vu une requête exécutée dans un fichier journal sur une application. et il contenait une requête comme:

SELECT ID FROM CUST_ATTR49 WHERE 1=0

à quoi sert une telle requête qui ne retournera rien?

31
MozenRath

Une requête comme celle-ci peut être utilisée pour envoyer une requête ping à la base de données. La clause:

WHERE 1=0

Garantit que les données ne sont pas renvoyées, donc pas de charge CPU, pas de trafic réseau ou autre consommation de ressources.

Une requête comme celle-ci peut tester:

  • disponibilité du serveur
  • Existence d'une table CUST_ATTR49
  • Existence d'une colonne ID
  • Garder une connexion vivante
  • Faire déclencher un déclencheur sans modifier aucune ligne
  • gérer de nombreuses conditions OR dans les requêtes dynamiques (par exemple WHERE 1=0 OR <condition>)
60
Andrea Colleoni

Un cas d'utilisation auquel je peux penser: vous avez un formulaire de filtre où vous ne voulez pas avoir de résultats de recherche. Si vous spécifiez un filtre, ils sont ajoutés à la clause where.

Ou il est généralement utilisé si vous devez créer une requête SQL à la main. Par exemple. vous ne voulez pas vérifier si la clause where est vide ou non .. et vous pouvez simplement ajouter des choses comme ceci:

where := "WHERE 0=1"

if X then where := where + " OR ... "
if Y then where := where + " OR ... "

(si vous connectez les clauses avec OR vous avez besoin de 0 = 1, si vous avez ET vous avez 1 = 1)

12
duedl0r

Cela peut également être utilisé pour extraire le schéma de table d'une table sans extraire de données à l'intérieur de cette table. Comme l'a dit Andrea Colleoni, ce seront les autres avantages de cette utilisation.

10
Darshana

Certains systèmes utilisent des scripts et peuvent définir dynamiquement les enregistrements sélectionnés à masquer d'une liste complète; une fausse condition doit donc être transmise au SQL. Par exemple, trois enregistrements sur 500 peuvent être marqués comme Confidentialité pour des raisons médicales et ne devraient pas être visibles par tout le monde. Une requête dynamique contrôlera les 500 enregistrements sont visibles par ceux des RH, tandis que 497 sont visibles par les gestionnaires. Une valeur serait transmise à la clause SQL définie de manière conditionnelle, c'est-à-dire `` WHERE 1 = 1 '' ou `` WHERE 1 = 0 '', selon qui est connecté au système.

3
Guest

C'est très bon dans la récupération de métadonnées et rend la chose générique. De nombreuses bases de données ont un optimiseur afin qu'elles ne l'exécutent pas réellement, mais c'est toujours une instruction SQL valide et devrait s'exécuter sur toutes les bases de données. Cela ne récupérera aucun résultat, mais vous savez que les noms de colonne sont valides, les types de données, etc. S'il ne s'exécute pas, vous savez que quelque chose ne va pas avec la base de données (pas en place, etc.). .

2
Jaideep Karande

Comme réponse - mais aussi comme clarification supplémentaire à ce que @AndreaColleoni a déjà mentionné:

gérer de nombreuses conditions OR dans les requêtes dynamiques (par exemple WHERE 1=0 OR <condition>)

Fonction comme interrupteur marche/arrêt

J'utilise ceci comme une instruction de commutation (marche/arrêt) pour des parties de ma requête.

Si je devais utiliser

WHERE 1=1
  AND (0=? OR first_name = ?) 
  AND (0=? OR last_name = ?)

Ensuite, je peux utiliser la première variable de liaison (?) pour activer ou désactiver le first_name critère de recherche. et la troisième variable de liaison (?) pour activer ou désactiver le last_name critère.

J'ai également ajouté un littéral 1=1 juste pour l'esthétique donc le texte de la requête s'aligne bien.

Pour ces deux critères, cela ne semble pas très utile, car il est peut-être plus facile de faire de même en créant dynamiquement votre condition WHERE en mettant seulement first_name ou last_name, ou les deux, ou aucun. Votre code devra donc créer dynamiquement 4 versions de la même requête. Imaginez ce qui se passerait si vous avez 10 critères différents à considérer, alors combien de combinaisons de la même requête devrez-vous gérer alors?

Optimisation du temps de compilation

Je pourrais aussi ajouter que l'ajout de 0 =? en tant que commutateur de variable de liaison ne fonctionnera pas très bien si tous vos critères sont indexés. L'optimiseur d'exécution qui sélectionnera les index et les plans d'exécution appropriés pourrait ne pas voir l'avantage de l'utilisation de l'index dans ces prédicats légèrement plus complexes. Par conséquent, je conseille généralement d'injecter explicitement le 0/1 dans votre requête (chaîne de concaténation dans votre sql, ou recherche/remplacement). Cela donnera au compilateur la possibilité d'optimiser les instructions redondantes et donnera au Runtime Executer une requête beaucoup plus simple à examiner.

(0=1 OR cond = ?) --> (cond = ?)
(0=0 OR cond = ?) --> Always True (ignore predicate)

Dans la deuxième instruction ci-dessus, le compilateur sait qu'il n'a même jamais à considérer la deuxième partie de la condition (cond = ?), et il supprimera simplement le prédicat entier. S'il s'agissait d'une variable de liaison, le compilateur n'aurait jamais pu accomplir cela.

Parce que vous injectez simplement et forcément un 0/1, il n'y a aucune chance d'injections SQL.

Dans mon SQL, comme une approche, je place généralement mes points d'injection sql en tant que $ {literal_name}, puis je recherche/remplace simplement en utilisant une expression régulière toute occurrence de $ {...} avec le littéral approprié, avant même de laisser le compilateur essayez-le. Cela conduit essentiellement à une requête stockée comme suit:

WHERE 1=1
  AND (0=${cond1_enabled} OR cond1 = ?)
  AND (0=${cond2_enabled} OR cond2 = ?)

Il semble bon, facile à comprendre, le compilateur le gère bien et le Runtime Cost Based Optimizer le comprend mieux et aura plus de chances de sélectionner le bon index.

Je porte un soin particulier à ce que j'injecte. La meilleure façon de transmettre des variables est et reste de lier des variables pour toutes les raisons évidentes.

2
YoYo

cité par Greg

Si la liste des conditions n'est pas connue au moment de la compilation et est plutôt créée au moment de l'exécution, vous n'avez pas à vous soucier de savoir si vous avez une ou plusieurs conditions. Vous pouvez tous les générer comme:

et

et les concaténer tous ensemble. Avec le 1 = 1 au début, l'initiale et a quelque chose à associer.

Je n'ai jamais vu cela utilisé pour tout type de protection contre les injections, car vous dites que cela ne semble pas aider beaucoup. Je l'ai vu utilisé comme commodité d'implémentation. Le moteur de requête SQL finira par ignorer le 1 = 1, il ne devrait donc pas avoir d'impact sur les performances.

Pourquoi quelqu'un utiliserait-il WHERE 1 = 1 AND <conditions> dans une clause SQL?

2
John Woo

Cela peut être utile lorsque seules les métadonnées de table sont souhaitées dans une application. Par exemple, si vous écrivez une application JDBC et souhaitez obtenir la taille d'affichage des colonnes des colonnes du tableau.

Coller un extrait de code ici

String query = "SELECT * from <Table_name> where 1=0";
PreparedStatement stmt = connection.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsMD  = rs.getMetaData();
int columnCount = rsMD.getColumnCount();
for(int i=0;i<columnCount;i++) {
    System.out.println("Column display size is: " + rsMD.getColumnDisplaySize(i+1));
}

Ici, avoir une requête comme "select * from table" peut entraîner des problèmes de performances si vous traitez des données énormes, car il essaiera de récupérer tous les enregistrements de la table. Au lieu de cela, si vous fournissez une requête telle que "select * from table where 1 =", il ne récupérera que les métadonnées de la table et non les enregistrements, il sera donc efficace.

1
kriti

Par tilisateur milso dans un autre thread , un autre but pour "WHERE 1 = 0":

CREATE TABLE New_table_name as select * FROM Old_table_name WHERE 1 = 2;

cela créera une nouvelle table avec le même schéma que l'ancienne table. (Très pratique si vous souhaitez charger des données pour les comparer)

1
Mark

Si l'utilisateur a l'intention d'ajouter uniquement des enregistrements, la méthode la plus rapide consiste à ouvrir le jeu d'enregistrements sans retourner aucun enregistrement existant.

1
Fred