web-dev-qa-db-fra.com

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

Pourquoi quelqu'un utiliserait-il WHERE 1=1 AND <conditions> dans une clause SQL (Soit le SQL obtenu par 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=1 aura le même résultat que injected OR 1=1.

Édition ultérieure: qu’en est-il de l’utilisation dans une définition de vue?


Merci pour vos réponses.

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

Prenons ceci par exemple:

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

Si la liste de conditions n'est pas connue au moment de la compilation et 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. Avec le 1=1 au début, le and initial a quelque chose à associer.

Je n'ai jamais vu cela utilisé pour un type quelconque de protection contre les injections, car vous dites qu'il ne semble pas que cela aiderait beaucoup. Je ai le voyons utilisé comme une commodité d'implémentation. Le moteur de requête SQL finira par ignorer le 1=1 et n'aura donc aucun impact sur les performances.

324
Greg Hewgill

Il suffit d'ajouter 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
112
Eduardo Molteni

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 spécifiez, 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 une chaîne "WHERE" devant elles.

36
Carl

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.

26
duckworth

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 voulez charger des données pour les comparaisons)

17
milso

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.

15
aku

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

11
asd

En fait, j'ai 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 (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 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 des codeurs lazy en créant dynamiquement une requête SQL.

Supposons que vous deviez créer dynamiquement une requête commençant par select * from t et vérifiant:

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

certaines personnes ajouteraient le premier avec un WHERE et les suivants avec un AND, ainsi:

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

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

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

J'ai trouvé utile ce modèle lorsque je teste ou vérifie plusieurs choses dans 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
8
Carlos Toledo

Bien que je sache que 1 = 1 serait utile pour le SQL généré, une technique que j’utilise dans PHP consiste à créer un tableau de clauses, puis à

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 un article!

6
sanbikinoraion

Voici un exemple étroitement lié: utilisation d'une instruction SQL MERGE pour mettre à jour la cible tabled à 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;
5
onedaywhen

Pourquoi quelqu'un utiliserait-il WHERE 1 = 1 AND <proper conditions>

J'ai v les frameworks homespun font des choses comme ceci ( blush ), car cela permet d'appliquer des méthodes d'analyse syntaxique paresseuses à la WHERE et AND mots-clés Sql.

Par exemple (j'utilise C # comme exemple ici), considérons 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 = 1 signifie qu'aucun code spécial n'est nécessaire:

  • Pour ET - soit zéro, un ou les deux prédicats (Bars et Baz) doivent être appliqués, ce qui déterminerait si le premier AND est requis. Comme 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, alors la WHERE doit être supprimée. Mais encore une fois, nous pouvons être paresseux, car nous sommes à nouveau garantis par au moins un prédicat.

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

5
StuartLC

Si vous êtes venu chercher 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.

4

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

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

2
JonWay

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 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 ci-dessous échantillon:

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
Eliseo Jr

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 une analyse 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 cela ne fonctionne pas toujours.

0
Big Al

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 where 1=1 à la fin et ajoutons ensuite toutes les clauses where.

Quelque chose comme

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

Ensuite, nous construirions la clause where comme celle-ci et la 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' or 'WHERE'.

0
Zo Has