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


258

Pourquoi quelqu'un utiliserait-il WHERE 1=1 AND <conditions>dans une clause SQL (Soit SQL obtenu via des chaînes concaténées, soit la définition de la vue)

J'ai vu quelque part que cela serait utilisé pour se protéger contre l'injection SQL, mais cela semble très étrange.

S'il y a injection WHERE 1 = 1 AND injected OR 1=1aurait le même résultat que injected OR 1=1.

Modification ultérieure: qu'en est-il de l'utilisation dans une définition de vue?


Merci pour vos réponses.

Pourtant, je ne comprends pas pourquoi quelqu'un utiliserait cette construction pour définir une vue, ou l'utiliser dans une procédure stockée.

Prenez ceci par exemple:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value

3
"pourquoi quelqu'un utiliserait-il cette construction pour définir une vue" Probablement par habitude. Il n'offre aucun avantage fonctionnel dans les requêtes statiques.
ADTC

Réponses:


346

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:

and <condition>

et les concaténer tous ensemble. Au 1=1début, l'initiale anda quelque chose à associer.

Je n'ai jamais vu cela utilisé pour n'importe quel 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=1donc il ne devrait avoir aucun impact sur les performances.


34
Parfois, il ne s'agit pas d'être paresseux, mais d'avoir un code plus propre.
Eduardo Molteni

39
traiter les AND et les COMMA à la fin n'est pas sale ... rien n'est plus propre en ayant 1 = 1 partout dans votre SQL.

21
DBA? À quoi servent-ils? :)
Eduardo Molteni

38
Les administrateurs de base de données sont là pour nettoyer les programmeurs qui pensent savoir utiliser efficacement les bases de données.
Adrian Pronk

23
"Paresseux" J'aime penser que c'est intelligent, pas paresseux. Vous évitez le code répétitif et les vérifications de condition inutiles. Sans pouvoir ajouter where 1=1(Oracle) ou where true(Postgres), je devrai vérifier pour chaque condition si c'est la première. Cela ne sert à rien, et cela n'ajoute que du code standard.
2014 ADTC

113

Ajout d'un exemple de code à la réponse de Greg:

dim sqlstmt as new StringBuilder
sqlstmt.add("SELECT * FROM Products")
sqlstmt.add(" WHERE 1=1") 

''// From now on you don't have to worry if you must 
''// append AND or WHERE because you know the WHERE is there
If ProductCategoryID <> 0 then
  sqlstmt.AppendFormat(" AND ProductCategoryID = {0}", trim(ProductCategoryID))
end if
If MinimunPrice > 0 then
  sqlstmt.AppendFormat(" AND Price >= {0}", trim(MinimunPrice))
end if

6
peu hacky, mais semble être une utilisation valide.
Mike

5
Ce devrait être la réponse acceptée. La pratique consiste vraiment à ne pas avoir à déterminer combien de conditions vous avez.
aglassman

38

Je l'ai vu utilisé lorsque le nombre de conditions peut être variable.

Vous pouvez concaténer des conditions à l'aide d'une chaîne "AND". Ensuite, au lieu de compter le nombre de conditions que vous transmettez, vous placez un "WHERE 1 = 1" à la fin de votre instruction SQL stock et ajoutez les conditions concaténées.

Fondamentalement, cela vous évite d'avoir à faire un test des conditions, puis à ajouter une chaîne "WHERE" devant elles.


28

Cela semble être un moyen paresseux de toujours savoir que votre clause WHERE est déjà définie et vous permet de continuer à ajouter des conditions sans avoir à vérifier si c'est la première.


12
"Paresseux" J'aime penser que c'est intelligent, pas paresseux. Vous évitez le code répétitif et les vérifications de condition inutiles. Sans pouvoir ajouter where 1=1(Oracle) ou where true(Postgres), je devrai vérifier pour chaque condition si c'est la première. Cela ne sert à rien, et cela n'ajoute que du code standard.
2014 ADTC

2
@ADTC L'écriture de code consiste souvent - sinon principalement - à gérer différentes conditions. C'est juste une autre condition qui doit être gérée, et je pense personnellement qu'il est paresseux de polluer le SQL généré. Si vous concevez votre code pour ajouter «Où 1 = 1» en UN seul endroit, vous pourriez - avec peu d'efforts supplémentaires - gérer la différence entre zéro et de nombreuses conditions dans ce seul endroit de votre code. Ma supposition est cependant que les partisans de «Où 1 = 1» le saupoudrent dans leur code, ce qui m'amène à la conclusion que la paresse engendre la paresse.
Jason S

@JasonS Laziness est le père d'Invention.
ADTC

@ADTC Je suis paresseux parce que je n'aime pas mettre à jour le code dans des centaines d'endroits, donc l'invention est mise en un seul endroit. Pour moi, WHERE 1=1le travail supplémentaire est de maintenir le même code à plusieurs endroits et de le lire dans tout votre SQL généré. Je suis plus paresseux que toi je pense!
Jason S

19

Indirectement pertinent: lorsque 1 = 2 est utilisé:

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)


3
Oublié d'ajouter, alors qu'il créera une nouvelle table avec les mêmes données que l'ancienne, la nouvelle table n'aura pas d'autres contraintes comme la clé étrangère de l'ancienne table
milso

16

L'expression 1 = 1 est couramment utilisée dans le code SQL généré. Cette expression peut simplifier la génération de code SQL en réduisant le nombre d'instructions conditionnelles.


11

En fait, j'ai vu ce genre de chose utilisé dans les rapports BIRT. La requête passée au runtime BIRT est de la forme:

select a,b,c from t where a = ?

et le '?' est remplacé lors de l'exécution par une valeur de paramètre réelle sélectionnée dans une liste déroulante. Les choix dans le menu déroulant sont donnés par:

select distinct a from t
union all
select '*' from sysibm.sysdummy1

afin que vous obteniez toutes les valeurs possibles plus " *". Si l'utilisateur sélectionne " *" dans la liste déroulante (ce qui signifie que toutes les valeurs de a doivent être sélectionnées), la requête doit être modifiée (par Javascript) avant d'être exécutée.

Depuis le "?" est un paramètre positionnel et DOIT y rester pour que d'autres choses fonctionnent, le Javascript modifie la requête pour qu'elle soit:

select a,b,c from t where ((a = ?) or (1==1))

Cela supprime essentiellement l'effet de la clause where tout en laissant le paramètre positionnel en place.

J'ai également vu le cas AND utilisé par les codeurs paresseux lors de la création dynamique d'une requête SQL.

Supposons que vous devez créer dynamiquement une requête qui commence par select * from tet vérifie:

  • le nom est Bob; et
  • le salaire est> 20 000 $

certaines personnes ajouteraient le premier avec un OERE et les suivantes avec un ET ainsi:

select * from t where name = 'Bob' and salary > 20000

Les programmeurs paresseux (et ce n'est pas nécessairement un mauvais trait) ne feraient pas de distinction entre les conditions ajoutées, ils commenceraient par select * from t where 1=1et ajouteraient simplement des clauses AND après cela.

select * from t where 1=1 and name = 'Bob' and salary > 20000

1
"Paresseux" J'aime penser que c'est intelligent, pas paresseux. Vous évitez le code répétitif et les vérifications de condition inutiles. Sans pouvoir ajouter where 1=1(Oracle) ou where true(Postgres), je devrai vérifier pour chaque condition si c'est la première. Cela ne sert à rien, et cela n'ajoute que du code standard.
2014 ADTC

1
@ADTC, je ne voulais pas dire paresseux dans le mauvais sens. En fait, paresseux est un bon trait en programmation :-) Je vais clarifier.
paxdiablo

La paresse est la racine de tout mal
Ivanzinho

11

J'ai trouvé ce modèle utile lorsque je teste ou vérifie deux fois des choses sur la base de données, donc je peux commenter très rapidement d'autres conditions:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
AND Table.Field=Value
AND Table.IsValid=true

se transforme en:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
--AND Table.Field=Value
--AND Table.IsValid=true

10

où 1 = 0, cela permet de vérifier si la table existe. Je ne sais pas pourquoi 1 = 1 est utilisé.


1
Vu, cela renvoyait un ensemble de résultats vide de la base de données à utiliser comme détenteur pour de nouveaux enregistrements.
Gary Kindel

6

Bien que je puisse voir que 1 = 1 serait utile pour le SQL généré, une technique que j'utilise en PHP consiste à créer un tableau de clauses, puis à le faire

implode (" AND ", $clauses);

évitant ainsi le problème d'avoir un ET avant ou arrière. Évidemment, cela n'est utile que si vous savez que vous allez avoir au moins une clause!


1
C'est là que le 1 = 1 entre en jeu. Cela vous donne "au moins une clause" pour que vous n'ayez pas à vous soucier de simplement gifler sur un "ET abc"
Carl

J'aime cette idée! Voir ici pour un exemple plus complet stackoverflow.com/questions/35326160/…
drooh

5

Voici un exemple étroitement lié: utiliser une MERGEinstruction SQL pour mettre à jour la cible déposée en utilisant toutes les valeurs de la table source où il n'y a pas d'attribut commun sur lequel se joindre, par exemple

MERGE INTO Circles
   USING 
      (
        SELECT pi
         FROM Constants
      ) AS SourceTable
   ON 1 = 1
WHEN MATCHED THEN 
  UPDATE
     SET circumference = 2 * SourceTable.pi * radius;

5

Pourquoi utiliser quelqu'un OERE 1 = 1 ET <proper conditions>

J'ai vu des frameworks homespun faire des choses comme ça ( blush ), car cela permet d'appliquer des pratiques d'analyse paresseuse aux mots-clés WHEREet ANDSql.

Par exemple (j'utilise C # comme exemple ici), considérez l'analyse conditionnelle des prédicats suivants dans une requête SQL string builder:

var sqlQuery = "SELECT * FROM FOOS WHERE 1 = 1"
if (shouldFilterForBars)
{
    sqlQuery = sqlQuery + " AND Bars > 3";
}
if (shouldFilterForBaz)
{
    sqlQuery = sqlQuery + " AND Baz < 12";
}

Le "bénéfice" de WHERE 1 = 1signifie qu'aucun code spécial n'est nécessaire:

  • Pour AND - que ce soit zéro, un ou les deux prédicats (Bars et Baz) doivent être appliqués, ce qui déterminerait si le premier ANDest requis. Puisque nous avons déjà au moins un prédicat avec le 1 = 1, cela signifie que ANDc'est toujours OK.
  • Pour aucun prédicat du tout - Dans le cas où il existe des prédicats ZÉRO, le WHEREdoit être supprimé. Mais encore une fois, nous pouvons être paresseux, car nous sommes à nouveau garant d'au moins un prédicat.

C'est évidemment une mauvaise idée et je recommanderais d'utiliser un cadre d'accès aux données ou ORM établi pour analyser les prédicats facultatifs et conditionnels de cette manière.


Ou si vous lancez le vôtre, le générateur de clause where doit être au même endroit dans votre code. Ensuite, vous pouvez gérer zéro prédicat ou plus de zéro prédicat en un seul emplacement dans votre code. Je soupçonne que l'existence de WHERE 1=1est un indicateur juste que ce n'est pas le cas, que la base de code est jonchée de bits de chaînes WHERE 1=1, ce qui m'indiquerait un problème d'architecture d'application, et je ne devinerais pas le seul!
Jason S

1
En fait, il n'y a rien de "mauvais" dans l'idée, encore moins une faute "évidente". Un ORM n'est pas non plus la bonne façon dans tous les cas. Apprenez les gens SQL et l'algèbre relationnelle ...
Hejazzman

4

Si vous êtes venu ici pour chercher WHERE 1, notez cela WHERE 1et ils WHERE 1=1sont identiques. WHERE 1est rarement utilisé car certains systèmes de base de données le rejettent en considérant qu'il WHERE 1n'est pas vraiment booléen.


2

Ceci est utile dans le cas où vous devez utiliser une requête dynamique dans laquelle, dans la clause where, vous devez ajouter des options de filtre. Comme si vous incluez les options 0 pour le statut est inactif, 1 pour actif. Sur la base des options, il n'y a que deux options disponibles (0 et 1) mais si vous souhaitez afficher tous les enregistrements, il est pratique d'inclure où fermer 1 = 1. Voir l'exemple ci-dessous:

Declare @SearchValue    varchar(8) 
Declare @SQLQuery varchar(max) = '
Select [FirstName]
    ,[LastName]
    ,[MiddleName]
    ,[BirthDate]
,Case
    when [Status] = 0 then ''Inactive''
    when [Status] = 1 then ''Active''
end as [Status]'

Declare @SearchOption nvarchar(100)
If (@SearchValue = 'Active')
Begin
    Set @SearchOption = ' Where a.[Status] = 1'
End

If (@SearchValue = 'Inactive')
Begin
    Set @SearchOption = ' Where a.[Status] = 0'
End

If (@SearchValue = 'All')
Begin
    Set @SearchOption = ' Where 1=1'
End

Set @SQLQuery = @SQLQuery + @SearchOption

Exec(@SQLQuery);

2

Après avoir passé en revue toutes les réponses, j'ai décidé d'effectuer une expérience comme

SELECT
*
FROM MyTable

WHERE 1=1

Puis j'ai vérifié avec d'autres numéros

WHERE 2=2
WHERE 10=10
WHERE 99=99

ect Après avoir effectué toutes les vérifications, la ville d'exécution des requêtes est la même. même sans la clause where. Je ne suis pas fan de la syntaxe


1

Je le fais généralement lorsque je crée du SQL dynamique pour un rapport contenant de nombreuses valeurs déroulantes qu'un utilisateur peut sélectionner. Étant donné que l'utilisateur peut ou non sélectionner les valeurs de chaque liste déroulante, nous finissons par avoir du mal à déterminer quelle condition était la première clause where. Donc, nous complétons la requête avec un where 1=1à la fin et ajoutons toutes les clauses where après cela.

Quelque chose comme

select column1, column2 from my table where 1=1 {name} {age};

Ensuite, nous construisions la clause where comme ceci et la transmettions comme valeur de paramètre

string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : "";

Comme la sélection de la clause where nous est inconnue au moment de l'exécution, cela nous aide beaucoup à déterminer s'il faut inclure un 'AND' or 'WHERE'.


0

L'utilisation d'un prédicat comme 1=1est un indice normal parfois utilisé pour forcer le plan d'accès à utiliser ou non une analyse d'index. La raison pour laquelle cela est utilisé est lorsque vous utilisez une requête jointe multi-imbriquée avec de nombreux prédicats dans la clause where où parfois même en utilisant tous les index, le plan d'accès lit chaque table - une analyse complète de la table. Ceci n'est qu'une des nombreuses astuces utilisées par les administrateurs de base de données pour inciter un dbms à utiliser un chemin plus efficace. N'en jetez pas un; vous avez besoin d'un dba pour analyser la requête car elle ne fonctionne pas toujours.


4
Avez-vous des citations qui documentent ce comportement pour certaines bases de données?
Joe

0

Voici un cas d'utilisation ... mais je ne suis pas trop préoccupé par les détails techniques de la raison pour laquelle je devrais ou non utiliser 1 = 1. J'écris une fonction, en utilisant pyodbc pour récupérer certaines données de SQL Server. Je cherchais un moyen de forcer un remplissage après le wheremot - clé dans mon code. C'était vraiment une excellente suggestion:

if _where == '': _where = '1=1'
...
...
...
cur.execute(f'select {predicate} from {table_name} where {_where}')

La raison en est que je n'ai pas pu implémenter le mot clé «where» ensemble dans la variable de clause _where. Donc, je pense que l'utilisation d'une condition fictive qui donne la valeur true ferait office de remplissage.


-1

Je suis tombé pour la première fois sur ce dos avec ADO et asp classique, la réponse que j'ai obtenue était: performance. si tu fais une ligne droite

Select * from tablename

et passez-le en tant que commande / texte sql, vous obtiendrez une augmentation notable des performances avec le

Where 1=1

ajouté, c'était une différence visible. quelque chose à voir avec le retour des en-têtes de table dès que la première condition est remplie, ou une autre folie, de toute façon, cela a accéléré les choses.


3
Si c'est vrai, pourquoi le SGBD n'ajoute-t-il pas toujours cela?
Carcamano

5
Pouvez-vous produire des preuves?
Peter G.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.