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

StackOverflow https://stackoverflow.com/questions/242822

  •  04-07-2019
  •  | 
  •  

Question

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

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

S'il y a une injection OERE 1 = 1 ET injecté OU 1 = 1 aurait le même résultat que injecté OU 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 dans une procédure stockée.

Prenons l'exemple suivant:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Était-ce utile?

La solution

Si la liste des conditions n'est pas connue au moment de la compilation mais est construite à l'exécution, vous n'avez pas à vous demander si vous avez une ou plusieurs conditions. Vous pouvez tous les générer comme:

and <condition>

et les concaténer tous ensemble. 1 = 1 au début, les codes et initiaux ont quelque chose à associer.

Je n'ai jamais vu cela utilisé pour un type quelconque de protection contre l'injection, car vous dites que cela ne semble pas que cela aiderait beaucoup. Je l'ai vu comme une commodité de mise en œuvre. Le moteur de requête SQL finira par ignorer 1 = 1 , de sorte qu'il ne devrait pas avoir d'impact sur les performances.

Autres conseils

Ajoutez simplement 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

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

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

En gros, cela vous évite de faire un test de conditions et d'ajouter ensuite un " WHERE " chaîne devant eux.

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 s'il s'agit de la première.

Indirectement pertinent: lorsque 1 = 2 est utilisé:

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

Ceci 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 comparaisons)

1 = 1 expression 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.

où 1 = 0, ceci est effectué pour vérifier si la table existe. Je ne sais pas pourquoi 1 = 1 est utilisé.

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

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

et le '?' est remplacé au moment de l'exécution par une valeur de paramètre réelle sélectionnée dans une liste déroulante. Les choix dans la liste déroulante 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 (signifiant 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 de position et DOIT y rester pour que d’autres choses fonctionnent, le Javascript modifie la requête pour être:

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

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

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

Dites que vous devez créer de manière dynamique une requête commençant par , sélectionnez * à partir de t et vérifie:

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

Certaines personnes ajouteraient le premier avec un WHERE et les suivants avec un AND, par exemple:

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

programmeurs fainéants (et ce n'est pas nécessairement un trait mauvais ) ne feraient pas la distinction entre les conditions ajoutées, ils commenceraient par select * à partir de t où 1 = 1 . et ajoutez simplement les clauses AND après cela.

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

J'ai trouvé ce modèle utile lorsque je teste ou vérifie deux fois des éléments de la base de données afin de pouvoir 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

Bien que je sache 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 à faire

implode (" AND ", $clauses);

évitant ainsi le problème d'avoir un ET en tête ou en fuite. Évidemment, cela n’est utile que si vous savez que vous allez avoir au moins une clause!

Voici un exemple étroitement lié: utilisation d'une instruction SQL MERGE pour mettre à jour la cible tablée à l'aide de toutes les valeurs de la table source où il n'y a pas d'attribut commun auquel 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;
  

Pourquoi quelqu'un utiliserait-il WHERE 1 = 1 ET < conditions appropriées >

J'ai vu des frameworks homespun qui font des choses comme celle-ci ( blush ), car permet d'appliquer des pratiques d'analyse paresseuse aux mots clés WHERE et AND SQL.

Par exemple (j'utilise l'exemple C # ici), considérons l'analyse conditionnelle des prédicats suivants dans une requête SQL constructeur de chaînes :

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 = 1 signifie qu'aucun code spécial n'est nécessaire:

  • Pour AND , vous devez appliquer un prédicat (Bars et Baz), ce qui déterminerait si le premier AND est requis. Puisque nous avons déjà au moins un prédicat avec le 1 = 1 , cela signifie que AND est toujours correct.
  • Pour aucun prédicat du tout - Dans le cas où il y a des prédicats ZERO, le WHERE doit être supprimé. Mais encore une fois, nous pouvons être paresseux, car nous avons à nouveau la garantie d’au moins un prédicat.

C’est évidemment une mauvaise idée. Nous vous recommandons d’utiliser un framework d’accès aux données établi ou des ORM pour analyser les prédicats facultatifs et conditionnels. de cette façon.

Si vous êtes venu ici à la recherche de WHERE 1 , notez que WHERE 1 et WHERE 1 = 1 sont identiques. WHERE 1 est rarement utilisé car certains systèmes de base de données le rejettent car WHERE 1 n'est pas vraiment booléen.

Ceci est utile dans le cas où vous devez utiliser une requête dynamique dans laquelle dans Clause, vous devez ajouter des options de filtrage. Comme si vous incluez les options 0 pour le statut est inactif, 1 pour actif. En fonction 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 dans 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);

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

SELECT
*
FROM MyTable

WHERE 1=1

Ensuite, 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 de la requête est la même. même sans la clause where. Je ne suis pas fan de la syntaxe

L'utilisation d'un prédicat tel que 1 = 1 est un indice normal parfois utilisé pour forcer le plan d'accès à utiliser ou non un balayage d'index. Cette raison est utilisée lorsque vous utilisez une requête jointe à plusieurs imbrications avec de nombreux prédicats dans la clause where où parfois même l'utilisation de tous les index force le plan d'accès à lire chaque table - une analyse complète de la table. Il ne s'agit que de l'un des nombreux conseils utilisés par les administrateurs de base de données pour amener un système de gestion de base à utiliser un chemin plus efficace. Juste n'en jetez pas un; vous avez besoin d’un dba pour analyser la requête car elle ne fonctionne pas toujours.

Je le fais généralement lorsque je crée du SQL dynamique pour un rapport comportant de nombreuses valeurs de liste déroulante 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. Nous complétons donc la requête avec un où 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 construirions la clause where comme ceci et le passerions en tant que 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" ou "WHERE".

J'ai rencontré ce problème avec ADO et l'asp classique, la réponse que j'ai obtenue était: performance. si vous faites une suite

Sélectionnez * dans le nom du fichier

et transmettez-le sous forme de commande / texte SQL, vous obtiendrez une augmentation de performances notable avec la

Où 1 = 1

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top