Pourquoi quelqu'un utiliserait-il WHERE 1 = 1 AND < conditions > dans une clause SQL?
-
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
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 le1 = 1
, cela signifie queAND
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.